From dbbea6713d6096cd1c411cb453a6b71292c78b33 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 26 Feb 2008 14:34:06 +0100 Subject: mac80211: add documentation book Quite a while ago I started this book. The required kernel-doc patches have since gone into the tree so it is now possible to build the book in mainline. The actual documentation is still rather incomplete and not all things are linked into the book, but this enables us to edit the documentation collaboratively, hopefully driver authors can add documentation based on their experience with mac80211. Signed-off-by: Johannes Berg Signed-off-by: John W. Linville --- Documentation/DocBook/Makefile | 3 +- Documentation/DocBook/mac80211.tmpl | 335 ++++++++++++++++++++++++++++++++++++ 2 files changed, 337 insertions(+), 1 deletion(-) create mode 100644 Documentation/DocBook/mac80211.tmpl (limited to 'Documentation') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 300e1707893f..9ebd1f00c6e7 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -11,7 +11,8 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ procfs-guide.xml writing_usb_driver.xml networking.xml \ kernel-api.xml filesystems.xml lsm.xml usb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ - genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml + genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ + mac80211.xml ### # The build process is as follows (targets): diff --git a/Documentation/DocBook/mac80211.tmpl b/Documentation/DocBook/mac80211.tmpl new file mode 100644 index 000000000000..b651e0a4b1c0 --- /dev/null +++ b/Documentation/DocBook/mac80211.tmpl @@ -0,0 +1,335 @@ + + + + + + The mac80211 subsystem for kernel developers + + + + Johannes + Berg + +
johannes@sipsolutions.net
+
+
+
+ + + 2007 + 2008 + Johannes Berg + + + + + This documentation is free software; you can redistribute + it and/or modify it under the terms of the GNU General Public + License version 2 as published by the Free Software Foundation. + + + + This documentation 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 documentation; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, + MA 02111-1307 USA + + + + For more details see the file COPYING in the source + distribution of Linux. + + + + +!Pinclude/net/mac80211.h Introduction +!Pinclude/net/mac80211.h Warning + +
+ + + + + + + The basic mac80211 driver interface + + + You should read and understand the information contained + within this part of the book while implementing a driver. + In some chapters, advanced usage is noted, that may be + skipped at first. + + + This part of the book only covers station and monitor mode + functionality, additional information required to implement + the other modes is covered in the second part of the book. + + + + + Basic hardware handling + TBD + + This chapter shall contain information on getting a hw + struct allocated and registered with mac80211. + + + Since it is required to allocate rates/modes before registering + a hw struct, this chapter shall also contain information on setting + up the rate/mode structs. + + + Additionally, some discussion about the callbacks and + the general programming model should be in here, including + the definition of ieee80211_ops which will be referred to + a lot. + + + Finally, a discussion of hardware capabilities should be done + with references to other parts of the book. + + +!Finclude/net/mac80211.h ieee80211_hw +!Finclude/net/mac80211.h ieee80211_hw_flags +!Finclude/net/mac80211.h SET_IEEE80211_DEV +!Finclude/net/mac80211.h SET_IEEE80211_PERM_ADDR +!Finclude/net/mac80211.h ieee80211_ops +!Finclude/net/mac80211.h ieee80211_alloc_hw +!Finclude/net/mac80211.h ieee80211_register_hw +!Finclude/net/mac80211.h ieee80211_get_tx_led_name +!Finclude/net/mac80211.h ieee80211_get_rx_led_name +!Finclude/net/mac80211.h ieee80211_get_assoc_led_name +!Finclude/net/mac80211.h ieee80211_get_radio_led_name +!Finclude/net/mac80211.h ieee80211_unregister_hw +!Finclude/net/mac80211.h ieee80211_free_hw + + + + PHY configuration + TBD + + This chapter should describe PHY handling including + start/stop callbacks and the various structures used. + +!Finclude/net/mac80211.h ieee80211_conf +!Finclude/net/mac80211.h ieee80211_conf_flags + + + + Virtual interfaces + TBD + + This chapter should describe virtual interface basics + that are relevant to the driver (VLANs, MGMT etc are not.) + It should explain the use of the add_iface/remove_iface + callbacks as well as the interface configuration callbacks. + + Things related to AP mode should be discussed there. + + Things related to supporting multiple interfaces should be + in the appropriate chapter, a BIG FAT note should be here about + this though and the recommendation to allow only a single + interface in STA mode at first! + +!Finclude/net/mac80211.h ieee80211_if_types +!Finclude/net/mac80211.h ieee80211_if_init_conf +!Finclude/net/mac80211.h ieee80211_if_conf + + + + Receive and transmit processing + + what should be here + TBD + + This should describe the receive and transmit + paths in mac80211/the drivers as well as + transmit status handling. + + + + Frame format +!Pinclude/net/mac80211.h Frame format + + + Alignment issues + TBD + + + Calling into mac80211 from interrupts +!Pinclude/net/mac80211.h Calling mac80211 from interrupts + + + functions/definitions +!Finclude/net/mac80211.h ieee80211_rx_status +!Finclude/net/mac80211.h mac80211_rx_flags +!Finclude/net/mac80211.h ieee80211_tx_control +!Finclude/net/mac80211.h ieee80211_tx_status_flags +!Finclude/net/mac80211.h ieee80211_rx +!Finclude/net/mac80211.h ieee80211_rx_irqsafe +!Finclude/net/mac80211.h ieee80211_tx_status +!Finclude/net/mac80211.h ieee80211_tx_status_irqsafe +!Finclude/net/mac80211.h ieee80211_rts_get +!Finclude/net/mac80211.h ieee80211_rts_duration +!Finclude/net/mac80211.h ieee80211_ctstoself_get +!Finclude/net/mac80211.h ieee80211_ctstoself_duration +!Finclude/net/mac80211.h ieee80211_generic_frame_duration +!Finclude/net/mac80211.h ieee80211_get_hdrlen_from_skb +!Finclude/net/mac80211.h ieee80211_get_hdrlen +!Finclude/net/mac80211.h ieee80211_wake_queue +!Finclude/net/mac80211.h ieee80211_stop_queue +!Finclude/net/mac80211.h ieee80211_start_queues +!Finclude/net/mac80211.h ieee80211_stop_queues +!Finclude/net/mac80211.h ieee80211_wake_queues + + + + + Frame filtering +!Pinclude/net/mac80211.h Frame filtering +!Finclude/net/mac80211.h ieee80211_filter_flags + + + + + Advanced driver interface + + + Information contained within this part of the book is + of interest only for advanced interaction of mac80211 + with drivers to exploit more hardware capabilities and + improve performance. + + + + + Hardware crypto acceleration +!Pinclude/net/mac80211.h Hardware crypto acceleration + +!Finclude/net/mac80211.h set_key_cmd +!Finclude/net/mac80211.h ieee80211_key_conf +!Finclude/net/mac80211.h ieee80211_key_alg +!Finclude/net/mac80211.h ieee80211_key_flags + + + + Multiple queues and QoS support + TBD +!Finclude/net/mac80211.h ieee80211_tx_queue_params +!Finclude/net/mac80211.h ieee80211_tx_queue_stats_data +!Finclude/net/mac80211.h ieee80211_tx_queue + + + + Access point mode support + TBD + Some parts of the if_conf should be discussed here instead + + Insert notes about VLAN interfaces with hw crypto here or + in the hw crypto chapter. + +!Finclude/net/mac80211.h ieee80211_get_buffered_bc +!Finclude/net/mac80211.h ieee80211_beacon_get + + + + Supporting multiple virtual interfaces + TBD + + Note: WDS with identical MAC address should almost always be OK + + + Insert notes about having multiple virtual interfaces with + different MAC addresses here, note which configurations are + supported by mac80211, add notes about supporting hw crypto + with it. + + + + + Hardware scan offload + TBD +!Finclude/net/mac80211.h ieee80211_scan_completed + + + + + Rate control interface + + TBD + + This part of the book describes the rate control algorithm + interface and how it relates to mac80211 and drivers. + + + + dummy chapter + TBD + + + + + Internals + + TBD + + This part of the book describes mac80211 internals. + + + + + Key handling + + Key handling basics +!Pnet/mac80211/key.c Key handling basics + + + MORE TBD + TBD + + + + + Receive processing + TBD + + + + Transmit processing + TBD + + + + Station info handling + + Programming information +!Fnet/mac80211/sta_info.h sta_info +!Fnet/mac80211/sta_info.h ieee80211_sta_info_flags + + + STA information lifetime rules +!Pnet/mac80211/sta_info.c STA information lifetime rules + + + + + Synchronisation + TBD + Locking, lots of RCU + + +
-- cgit v1.2.3 From 2079fcdc06ea01c084044c348dbcd7b3e335ad49 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 4 Mar 2008 15:26:12 -0800 Subject: the scheduled bcm43xx removal Signed-off-by: Adrian Bunk Cc: Cc: Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 9 - Documentation/laptops/acer-wmi.txt | 2 +- Documentation/networking/bcm43xx.txt | 89 - MAINTAINERS | 9 - drivers/net/wireless/Kconfig | 1 - drivers/net/wireless/Makefile | 1 - drivers/net/wireless/bcm43xx/Kconfig | 70 - drivers/net/wireless/bcm43xx/Makefile | 12 - drivers/net/wireless/bcm43xx/bcm43xx.h | 997 ------ drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c | 556 --- drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h | 118 - drivers/net/wireless/bcm43xx/bcm43xx_dma.c | 1263 ------- drivers/net/wireless/bcm43xx/bcm43xx_dma.h | 386 --- drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c | 50 - drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h | 8 - drivers/net/wireless/bcm43xx/bcm43xx_ilt.c | 352 -- drivers/net/wireless/bcm43xx/bcm43xx_ilt.h | 33 - drivers/net/wireless/bcm43xx/bcm43xx_leds.c | 307 -- drivers/net/wireless/bcm43xx/bcm43xx_leds.h | 62 - drivers/net/wireless/bcm43xx/bcm43xx_main.c | 4281 ------------------------ drivers/net/wireless/bcm43xx/bcm43xx_main.h | 133 - drivers/net/wireless/bcm43xx/bcm43xx_phy.c | 2346 ------------- drivers/net/wireless/bcm43xx/bcm43xx_phy.h | 78 - drivers/net/wireless/bcm43xx/bcm43xx_pio.c | 674 ---- drivers/net/wireless/bcm43xx/bcm43xx_pio.h | 163 - drivers/net/wireless/bcm43xx/bcm43xx_power.c | 393 --- drivers/net/wireless/bcm43xx/bcm43xx_power.h | 56 - drivers/net/wireless/bcm43xx/bcm43xx_radio.c | 2170 ------------ drivers/net/wireless/bcm43xx/bcm43xx_radio.h | 115 - drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c | 471 --- drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h | 9 - drivers/net/wireless/bcm43xx/bcm43xx_wx.c | 1035 ------ drivers/net/wireless/bcm43xx/bcm43xx_wx.h | 36 - drivers/net/wireless/bcm43xx/bcm43xx_xmit.c | 565 ---- drivers/net/wireless/bcm43xx/bcm43xx_xmit.h | 150 - 35 files changed, 1 insertion(+), 16999 deletions(-) delete mode 100644 Documentation/networking/bcm43xx.txt delete mode 100644 drivers/net/wireless/bcm43xx/Kconfig delete mode 100644 drivers/net/wireless/bcm43xx/Makefile delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_dma.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_dma.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ilt.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_ilt.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_leds.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_leds.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_main.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_main.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_phy.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_phy.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_pio.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_pio.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_power.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_power.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_radio.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_radio.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_wx.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_wx.h delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_xmit.c delete mode 100644 drivers/net/wireless/bcm43xx/bcm43xx_xmit.h (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 4d3aa519eadf..dade1d14f5b2 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -230,15 +230,6 @@ Who: Jean Delvare --------------------------- -What: bcm43xx wireless network driver -When: 2.6.26 -Files: drivers/net/wireless/bcm43xx -Why: This driver's functionality has been replaced by the - mac80211-based b43 and b43legacy drivers. -Who: John W. Linville - ---------------------------- - What: ieee80211 softmac wireless networking component When: 2.6.26 (or after removal of bcm43xx and port of zd1211rw to mac80211) Files: net/ieee80211/softmac diff --git a/Documentation/laptops/acer-wmi.txt b/Documentation/laptops/acer-wmi.txt index b06696329cff..68ef0fc04787 100644 --- a/Documentation/laptops/acer-wmi.txt +++ b/Documentation/laptops/acer-wmi.txt @@ -80,7 +80,7 @@ once you enable the radio, will depend on your hardware and driver combination. e.g. With the BCM4318 on the Acer Aspire 5020 series: ndiswrapper: Light blinks on when transmitting -bcm43xx/b43: Solid light, blinks off when transmitting +b43: Solid light, blinks off when transmitting Wireless radio control is unconditionally enabled - all Acer laptops that support acer-wmi come with built-in wireless. However, should you feel so inclined to diff --git a/Documentation/networking/bcm43xx.txt b/Documentation/networking/bcm43xx.txt deleted file mode 100644 index d602c8d6ff3e..000000000000 --- a/Documentation/networking/bcm43xx.txt +++ /dev/null @@ -1,89 +0,0 @@ - - BCM43xx Linux Driver Project - ============================ - -Introduction ------------- - -Many of the wireless devices found in modern notebook computers are -based on the wireless chips produced by Broadcom. These devices have -been a problem for Linux users as there is no open-source driver -available. In addition, Broadcom has not released specifications -for the device, and driver availability has been limited to the -binary-only form used in the GPL versions of AP hardware such as the -Linksys WRT54G, and the Windows and OS X drivers. Before this project -began, the only way to use these devices were to use the Windows or -OS X drivers with either the Linuxant or ndiswrapper modules. There -is a strong penalty if this method is used as loading the binary-only -module "taints" the kernel, and no kernel developer will help diagnose -any kernel problems. - -Development ------------ - -This driver has been developed using -a clean-room technique that is described at -http://bcm-specs.sipsolutions.net/ReverseEngineeringProcess. For legal -reasons, none of the clean-room crew works on the on the Linux driver, -and none of the Linux developers sees anything but the specifications, -which are the ultimate product of the reverse-engineering group. - -Software --------- - -Since the release of the 2.6.17 kernel, the bcm43xx driver has been -distributed with the kernel source, and is prebuilt in most, if not -all, distributions. There is, however, additional software that is -required. The firmware used by the chip is the intellectual property -of Broadcom and they have not given the bcm43xx team redistribution -rights to this firmware. Since we cannot legally redistribute -the firmware we cannot include it with the driver. Furthermore, it -cannot be placed in the downloadable archives of any distributing -organization; therefore, the user is responsible for obtaining the -firmware and placing it in the appropriate location so that the driver -can find it when initializing. - -To help with this process, the bcm43xx developers provide a separate -program named bcm43xx-fwcutter to "cut" the firmware out of a -Windows or OS X driver and write the extracted files to the proper -location. This program is usually provided with the distribution; -however, it may be downloaded from - -http://developer.berlios.de/project/showfiles.php?group_id=4547 - -The firmware is available in two versions. V3 firmware is used with -the in-kernel bcm43xx driver that uses a software MAC layer called -SoftMAC, and will have a microcode revision of 0x127 or smaller. The -V4 firmware is used by an out-of-kernel driver employing a variation of -the Devicescape MAC layer known as d80211. Once bcm43xx-d80211 reaches -a satisfactory level of development, it will replace bcm43xx-softmac -in the kernel as it is much more flexible and powerful. - -A source for the latest V3 firmware is - -http://downloads.openwrt.org/sources/wl_apsta-3.130.20.0.o - -Once this file is downloaded, the command -'bcm43xx-fwcutter -w ' -will extract the microcode and write it to directory -. The correct directory will depend on your distribution; -however, most use '/lib/firmware'. Once this step is completed, -the bcm3xx driver should load when the system is booted. To see -any messages relating to the driver, issue the command 'dmesg | -grep bcm43xx' from a terminal window. If there are any problems, -please send that output to Bcm43xx-dev@lists.berlios.de. - -Although the driver has been in-kernel since 2.6.17, the earliest -version is quite limited in its capability. Patches that include -all features of later versions are available for the stable kernel -versions from 2.6.18. These will be needed if you use a BCM4318, -or a PCI Express version (BCM4311 and BCM4312). In addition, if you -have an early BCM4306 and more than 1 GB RAM, your kernel will need -to be patched. These patches, which are being updated regularly, -are available at ftp://lwfinger.dynalias.org/patches. Look for -combined_2.6.YY.patch. Of course you will need kernel source downloaded -from kernel.org, or the source from your distribution. - -If you build your own kernel, please enable CONFIG_BCM43XX_DEBUG -and CONFIG_IEEE80211_SOFTMAC_DEBUG. The log information provided is -essential for solving any problems. diff --git a/MAINTAINERS b/MAINTAINERS index 93e0de955b4b..38b767611bbf 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -825,15 +825,6 @@ L: linux-wireless@vger.kernel.org W: http://linuxwireless.org/en/users/Drivers/b43 S: Maintained -BCM43XX WIRELESS DRIVER (SOFTMAC BASED VERSION) -P: Larry Finger -M: Larry.Finger@lwfinger.net -P: Stefano Brivio -M: stefano.brivio@polimi.it -L: linux-wireless@vger.kernel.org -W: http://bcm43xx.berlios.de/ -S: Obsolete - BEFS FILE SYSTEM P: Sergey S. Kostyliov M: rathamahata@php4.ru diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 3c3ef966c95b..f4ca6fd4a29f 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig @@ -741,7 +741,6 @@ config P54_PCI source "drivers/net/wireless/ath5k/Kconfig" source "drivers/net/wireless/iwlwifi/Kconfig" source "drivers/net/wireless/hostap/Kconfig" -source "drivers/net/wireless/bcm43xx/Kconfig" source "drivers/net/wireless/b43/Kconfig" source "drivers/net/wireless/b43legacy/Kconfig" source "drivers/net/wireless/zd1211rw/Kconfig" diff --git a/drivers/net/wireless/Makefile b/drivers/net/wireless/Makefile index 091dfe2e574e..dd3899747b5c 100644 --- a/drivers/net/wireless/Makefile +++ b/drivers/net/wireless/Makefile @@ -35,7 +35,6 @@ obj-$(CONFIG_PCMCIA_ATMEL) += atmel_cs.o obj-$(CONFIG_PRISM54) += prism54/ obj-$(CONFIG_HOSTAP) += hostap/ -obj-$(CONFIG_BCM43XX) += bcm43xx/ obj-$(CONFIG_B43) += b43/ obj-$(CONFIG_B43LEGACY) += b43legacy/ obj-$(CONFIG_ZD1211RW) += zd1211rw/ diff --git a/drivers/net/wireless/bcm43xx/Kconfig b/drivers/net/wireless/bcm43xx/Kconfig deleted file mode 100644 index afb8f4305c24..000000000000 --- a/drivers/net/wireless/bcm43xx/Kconfig +++ /dev/null @@ -1,70 +0,0 @@ -config BCM43XX - tristate "Broadcom BCM43xx wireless support (DEPRECATED)" - depends on PCI && IEEE80211 && IEEE80211_SOFTMAC && WLAN_80211 && (!SSB_B43_PCI_BRIDGE || SSB != y) && EXPERIMENTAL - select WIRELESS_EXT - select FW_LOADER - select HW_RANDOM - ---help--- - This is an experimental driver for the Broadcom 43xx wireless - chip, found in the Apple Airport Extreme and various other - devices. This driver is deprecated and will be removed - from the kernel in the near future. It has been replaced - by the b43 and b43legacy drivers. - -config BCM43XX_DEBUG - bool "Broadcom BCM43xx debugging (RECOMMENDED)" - depends on BCM43XX - default y - ---help--- - Broadcom 43xx debugging messages. - Say Y, because the driver is still very experimental and - this will help you get it running. - -config BCM43XX_DMA - bool - depends on BCM43XX - -config BCM43XX_PIO - bool - depends on BCM43XX - -choice - prompt "BCM43xx data transfer mode" - depends on BCM43XX - default BCM43XX_DMA_AND_PIO_MODE - -config BCM43XX_DMA_AND_PIO_MODE - bool "DMA + PIO" - select BCM43XX_DMA - select BCM43XX_PIO - ---help--- - Include both, Direct Memory Access (DMA) and Programmed I/O (PIO) - data transfer modes. - The actually used mode is selectable through the module - parameter "pio". If the module parameter is pio=0, DMA is used. - Otherwise PIO is used. DMA is default. - - If unsure, choose this option. - -config BCM43XX_DMA_MODE - bool "DMA (Direct Memory Access) only" - select BCM43XX_DMA - ---help--- - Only include Direct Memory Access (DMA). - This reduces the size of the driver module, by omitting the PIO code. - -config BCM43XX_PIO_MODE - bool "PIO (Programmed I/O) only" - select BCM43XX_PIO - ---help--- - Only include Programmed I/O (PIO). - This reduces the size of the driver module, by omitting the DMA code. - Please note that PIO transfers are slow (compared to DMA). - - Also note that not all devices of the 43xx series support PIO. - The 4306 (Apple Airport Extreme and others) supports PIO, while - the 4318 is known to _not_ support PIO. - - Only use PIO, if DMA does not work for you. - -endchoice diff --git a/drivers/net/wireless/bcm43xx/Makefile b/drivers/net/wireless/bcm43xx/Makefile deleted file mode 100644 index bb5220c629d2..000000000000 --- a/drivers/net/wireless/bcm43xx/Makefile +++ /dev/null @@ -1,12 +0,0 @@ -obj-$(CONFIG_BCM43XX) += bcm43xx.o -bcm43xx-obj-$(CONFIG_BCM43XX_DEBUG) += bcm43xx_debugfs.o - -bcm43xx-obj-$(CONFIG_BCM43XX_DMA) += bcm43xx_dma.o -bcm43xx-obj-$(CONFIG_BCM43XX_PIO) += bcm43xx_pio.o - -bcm43xx-objs := bcm43xx_main.o bcm43xx_ilt.o \ - bcm43xx_radio.o bcm43xx_phy.o \ - bcm43xx_power.o bcm43xx_wx.o \ - bcm43xx_leds.o bcm43xx_ethtool.o \ - bcm43xx_xmit.o bcm43xx_sysfs.o \ - $(bcm43xx-obj-y) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx.h b/drivers/net/wireless/bcm43xx/bcm43xx.h deleted file mode 100644 index 2ebd2edf5862..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx.h +++ /dev/null @@ -1,997 +0,0 @@ -#ifndef BCM43xx_H_ -#define BCM43xx_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "bcm43xx_debugfs.h" -#include "bcm43xx_leds.h" - - -#define PFX KBUILD_MODNAME ": " - -#define BCM43xx_SWITCH_CORE_MAX_RETRIES 50 -#define BCM43xx_IRQWAIT_MAX_RETRIES 100 - -#define BCM43xx_IO_SIZE 8192 - -/* Active Core PCI Configuration Register. */ -#define BCM43xx_PCICFG_ACTIVE_CORE 0x80 -/* SPROM control register. */ -#define BCM43xx_PCICFG_SPROMCTL 0x88 -/* Interrupt Control PCI Configuration Register. (Only on PCI cores with rev >= 6) */ -#define BCM43xx_PCICFG_ICR 0x94 - -/* MMIO offsets */ -#define BCM43xx_MMIO_DMA0_REASON 0x20 -#define BCM43xx_MMIO_DMA0_IRQ_MASK 0x24 -#define BCM43xx_MMIO_DMA1_REASON 0x28 -#define BCM43xx_MMIO_DMA1_IRQ_MASK 0x2C -#define BCM43xx_MMIO_DMA2_REASON 0x30 -#define BCM43xx_MMIO_DMA2_IRQ_MASK 0x34 -#define BCM43xx_MMIO_DMA3_REASON 0x38 -#define BCM43xx_MMIO_DMA3_IRQ_MASK 0x3C -#define BCM43xx_MMIO_DMA4_REASON 0x40 -#define BCM43xx_MMIO_DMA4_IRQ_MASK 0x44 -#define BCM43xx_MMIO_DMA5_REASON 0x48 -#define BCM43xx_MMIO_DMA5_IRQ_MASK 0x4C -#define BCM43xx_MMIO_STATUS_BITFIELD 0x120 -#define BCM43xx_MMIO_STATUS2_BITFIELD 0x124 -#define BCM43xx_MMIO_GEN_IRQ_REASON 0x128 -#define BCM43xx_MMIO_GEN_IRQ_MASK 0x12C -#define BCM43xx_MMIO_RAM_CONTROL 0x130 -#define BCM43xx_MMIO_RAM_DATA 0x134 -#define BCM43xx_MMIO_PS_STATUS 0x140 -#define BCM43xx_MMIO_RADIO_HWENABLED_HI 0x158 -#define BCM43xx_MMIO_SHM_CONTROL 0x160 -#define BCM43xx_MMIO_SHM_DATA 0x164 -#define BCM43xx_MMIO_SHM_DATA_UNALIGNED 0x166 -#define BCM43xx_MMIO_XMITSTAT_0 0x170 -#define BCM43xx_MMIO_XMITSTAT_1 0x174 -#define BCM43xx_MMIO_REV3PLUS_TSF_LOW 0x180 /* core rev >= 3 only */ -#define BCM43xx_MMIO_REV3PLUS_TSF_HIGH 0x184 /* core rev >= 3 only */ - -/* 32-bit DMA */ -#define BCM43xx_MMIO_DMA32_BASE0 0x200 -#define BCM43xx_MMIO_DMA32_BASE1 0x220 -#define BCM43xx_MMIO_DMA32_BASE2 0x240 -#define BCM43xx_MMIO_DMA32_BASE3 0x260 -#define BCM43xx_MMIO_DMA32_BASE4 0x280 -#define BCM43xx_MMIO_DMA32_BASE5 0x2A0 -/* 64-bit DMA */ -#define BCM43xx_MMIO_DMA64_BASE0 0x200 -#define BCM43xx_MMIO_DMA64_BASE1 0x240 -#define BCM43xx_MMIO_DMA64_BASE2 0x280 -#define BCM43xx_MMIO_DMA64_BASE3 0x2C0 -#define BCM43xx_MMIO_DMA64_BASE4 0x300 -#define BCM43xx_MMIO_DMA64_BASE5 0x340 -/* PIO */ -#define BCM43xx_MMIO_PIO1_BASE 0x300 -#define BCM43xx_MMIO_PIO2_BASE 0x310 -#define BCM43xx_MMIO_PIO3_BASE 0x320 -#define BCM43xx_MMIO_PIO4_BASE 0x330 - -#define BCM43xx_MMIO_PHY_VER 0x3E0 -#define BCM43xx_MMIO_PHY_RADIO 0x3E2 -#define BCM43xx_MMIO_ANTENNA 0x3E8 -#define BCM43xx_MMIO_CHANNEL 0x3F0 -#define BCM43xx_MMIO_CHANNEL_EXT 0x3F4 -#define BCM43xx_MMIO_RADIO_CONTROL 0x3F6 -#define BCM43xx_MMIO_RADIO_DATA_HIGH 0x3F8 -#define BCM43xx_MMIO_RADIO_DATA_LOW 0x3FA -#define BCM43xx_MMIO_PHY_CONTROL 0x3FC -#define BCM43xx_MMIO_PHY_DATA 0x3FE -#define BCM43xx_MMIO_MACFILTER_CONTROL 0x420 -#define BCM43xx_MMIO_MACFILTER_DATA 0x422 -#define BCM43xx_MMIO_RADIO_HWENABLED_LO 0x49A -#define BCM43xx_MMIO_GPIO_CONTROL 0x49C -#define BCM43xx_MMIO_GPIO_MASK 0x49E -#define BCM43xx_MMIO_TSF_0 0x632 /* core rev < 3 only */ -#define BCM43xx_MMIO_TSF_1 0x634 /* core rev < 3 only */ -#define BCM43xx_MMIO_TSF_2 0x636 /* core rev < 3 only */ -#define BCM43xx_MMIO_TSF_3 0x638 /* core rev < 3 only */ -#define BCM43xx_MMIO_RNG 0x65A -#define BCM43xx_MMIO_POWERUP_DELAY 0x6A8 - -/* SPROM offsets. */ -#define BCM43xx_SPROM_BASE 0x1000 -#define BCM43xx_SPROM_BOARDFLAGS2 0x1c -#define BCM43xx_SPROM_IL0MACADDR 0x24 -#define BCM43xx_SPROM_ET0MACADDR 0x27 -#define BCM43xx_SPROM_ET1MACADDR 0x2a -#define BCM43xx_SPROM_ETHPHY 0x2d -#define BCM43xx_SPROM_BOARDREV 0x2e -#define BCM43xx_SPROM_PA0B0 0x2f -#define BCM43xx_SPROM_PA0B1 0x30 -#define BCM43xx_SPROM_PA0B2 0x31 -#define BCM43xx_SPROM_WL0GPIO0 0x32 -#define BCM43xx_SPROM_WL0GPIO2 0x33 -#define BCM43xx_SPROM_MAXPWR 0x34 -#define BCM43xx_SPROM_PA1B0 0x35 -#define BCM43xx_SPROM_PA1B1 0x36 -#define BCM43xx_SPROM_PA1B2 0x37 -#define BCM43xx_SPROM_IDL_TSSI_TGT 0x38 -#define BCM43xx_SPROM_BOARDFLAGS 0x39 -#define BCM43xx_SPROM_ANTENNA_GAIN 0x3a -#define BCM43xx_SPROM_VERSION 0x3f - -/* BCM43xx_SPROM_BOARDFLAGS values */ -#define BCM43xx_BFL_BTCOEXIST 0x0001 /* implements Bluetooth coexistance */ -#define BCM43xx_BFL_PACTRL 0x0002 /* GPIO 9 controlling the PA */ -#define BCM43xx_BFL_AIRLINEMODE 0x0004 /* implements GPIO 13 radio disable indication */ -#define BCM43xx_BFL_RSSI 0x0008 /* software calculates nrssi slope. */ -#define BCM43xx_BFL_ENETSPI 0x0010 /* has ephy roboswitch spi */ -#define BCM43xx_BFL_XTAL_NOSLOW 0x0020 /* no slow clock available */ -#define BCM43xx_BFL_CCKHIPWR 0x0040 /* can do high power CCK transmission */ -#define BCM43xx_BFL_ENETADM 0x0080 /* has ADMtek switch */ -#define BCM43xx_BFL_ENETVLAN 0x0100 /* can do vlan */ -#define BCM43xx_BFL_AFTERBURNER 0x0200 /* supports Afterburner mode */ -#define BCM43xx_BFL_NOPCI 0x0400 /* leaves PCI floating */ -#define BCM43xx_BFL_FEM 0x0800 /* supports the Front End Module */ -#define BCM43xx_BFL_EXTLNA 0x1000 /* has an external LNA */ -#define BCM43xx_BFL_HGPA 0x2000 /* had high gain PA */ -#define BCM43xx_BFL_BTCMOD 0x4000 /* BFL_BTCOEXIST is given in alternate GPIOs */ -#define BCM43xx_BFL_ALTIQ 0x8000 /* alternate I/Q settings */ - -/* GPIO register offset, in both ChipCommon and PCI core. */ -#define BCM43xx_GPIO_CONTROL 0x6c - -/* SHM Routing */ -#define BCM43xx_SHM_SHARED 0x0001 -#define BCM43xx_SHM_WIRELESS 0x0002 -#define BCM43xx_SHM_PCM 0x0003 -#define BCM43xx_SHM_HWMAC 0x0004 -#define BCM43xx_SHM_UCODE 0x0300 - -/* MacFilter offsets. */ -#define BCM43xx_MACFILTER_SELF 0x0000 -#define BCM43xx_MACFILTER_ASSOC 0x0003 - -/* Chipcommon registers. */ -#define BCM43xx_CHIPCOMMON_CAPABILITIES 0x04 -#define BCM43xx_CHIPCOMMON_CTL 0x28 -#define BCM43xx_CHIPCOMMON_PLLONDELAY 0xB0 -#define BCM43xx_CHIPCOMMON_FREFSELDELAY 0xB4 -#define BCM43xx_CHIPCOMMON_SLOWCLKCTL 0xB8 -#define BCM43xx_CHIPCOMMON_SYSCLKCTL 0xC0 - -/* PCI core specific registers. */ -#define BCM43xx_PCICORE_BCAST_ADDR 0x50 -#define BCM43xx_PCICORE_BCAST_DATA 0x54 -#define BCM43xx_PCICORE_SBTOPCI2 0x108 - -/* SBTOPCI2 values. */ -#define BCM43xx_SBTOPCI2_PREFETCH 0x4 -#define BCM43xx_SBTOPCI2_BURST 0x8 -#define BCM43xx_SBTOPCI2_MEMREAD_MULTI 0x20 - -/* PCI-E core registers. */ -#define BCM43xx_PCIECORE_REG_ADDR 0x0130 -#define BCM43xx_PCIECORE_REG_DATA 0x0134 -#define BCM43xx_PCIECORE_MDIO_CTL 0x0128 -#define BCM43xx_PCIECORE_MDIO_DATA 0x012C - -/* PCI-E registers. */ -#define BCM43xx_PCIE_TLP_WORKAROUND 0x0004 -#define BCM43xx_PCIE_DLLP_LINKCTL 0x0100 - -/* PCI-E MDIO bits. */ -#define BCM43xx_PCIE_MDIO_ST 0x40000000 -#define BCM43xx_PCIE_MDIO_WT 0x10000000 -#define BCM43xx_PCIE_MDIO_DEV 22 -#define BCM43xx_PCIE_MDIO_REG 18 -#define BCM43xx_PCIE_MDIO_TA 0x00020000 -#define BCM43xx_PCIE_MDIO_TC 0x0100 - -/* MDIO devices. */ -#define BCM43xx_MDIO_SERDES_RX 0x1F - -/* SERDES RX registers. */ -#define BCM43xx_SERDES_RXTIMER 0x2 -#define BCM43xx_SERDES_CDR 0x6 -#define BCM43xx_SERDES_CDR_BW 0x7 - -/* Chipcommon capabilities. */ -#define BCM43xx_CAPABILITIES_PCTL 0x00040000 -#define BCM43xx_CAPABILITIES_PLLMASK 0x00030000 -#define BCM43xx_CAPABILITIES_PLLSHIFT 16 -#define BCM43xx_CAPABILITIES_FLASHMASK 0x00000700 -#define BCM43xx_CAPABILITIES_FLASHSHIFT 8 -#define BCM43xx_CAPABILITIES_EXTBUSPRESENT 0x00000040 -#define BCM43xx_CAPABILITIES_UARTGPIO 0x00000020 -#define BCM43xx_CAPABILITIES_UARTCLOCKMASK 0x00000018 -#define BCM43xx_CAPABILITIES_UARTCLOCKSHIFT 3 -#define BCM43xx_CAPABILITIES_MIPSBIGENDIAN 0x00000004 -#define BCM43xx_CAPABILITIES_NRUARTSMASK 0x00000003 - -/* PowerControl */ -#define BCM43xx_PCTL_IN 0xB0 -#define BCM43xx_PCTL_OUT 0xB4 -#define BCM43xx_PCTL_OUTENABLE 0xB8 -#define BCM43xx_PCTL_XTAL_POWERUP 0x40 -#define BCM43xx_PCTL_PLL_POWERDOWN 0x80 - -/* PowerControl Clock Modes */ -#define BCM43xx_PCTL_CLK_FAST 0x00 -#define BCM43xx_PCTL_CLK_SLOW 0x01 -#define BCM43xx_PCTL_CLK_DYNAMIC 0x02 - -#define BCM43xx_PCTL_FORCE_SLOW 0x0800 -#define BCM43xx_PCTL_FORCE_PLL 0x1000 -#define BCM43xx_PCTL_DYN_XTAL 0x2000 - -/* COREIDs */ -#define BCM43xx_COREID_CHIPCOMMON 0x800 -#define BCM43xx_COREID_ILINE20 0x801 -#define BCM43xx_COREID_SDRAM 0x803 -#define BCM43xx_COREID_PCI 0x804 -#define BCM43xx_COREID_MIPS 0x805 -#define BCM43xx_COREID_ETHERNET 0x806 -#define BCM43xx_COREID_V90 0x807 -#define BCM43xx_COREID_USB11_HOSTDEV 0x80a -#define BCM43xx_COREID_IPSEC 0x80b -#define BCM43xx_COREID_PCMCIA 0x80d -#define BCM43xx_COREID_EXT_IF 0x80f -#define BCM43xx_COREID_80211 0x812 -#define BCM43xx_COREID_MIPS_3302 0x816 -#define BCM43xx_COREID_USB11_HOST 0x817 -#define BCM43xx_COREID_USB11_DEV 0x818 -#define BCM43xx_COREID_USB20_HOST 0x819 -#define BCM43xx_COREID_USB20_DEV 0x81a -#define BCM43xx_COREID_SDIO_HOST 0x81b -#define BCM43xx_COREID_PCIE 0x820 - -/* Core Information Registers */ -#define BCM43xx_CIR_BASE 0xf00 -#define BCM43xx_CIR_SBTPSFLAG (BCM43xx_CIR_BASE + 0x18) -#define BCM43xx_CIR_SBIMSTATE (BCM43xx_CIR_BASE + 0x90) -#define BCM43xx_CIR_SBINTVEC (BCM43xx_CIR_BASE + 0x94) -#define BCM43xx_CIR_SBTMSTATELOW (BCM43xx_CIR_BASE + 0x98) -#define BCM43xx_CIR_SBTMSTATEHIGH (BCM43xx_CIR_BASE + 0x9c) -#define BCM43xx_CIR_SBIMCONFIGLOW (BCM43xx_CIR_BASE + 0xa8) -#define BCM43xx_CIR_SB_ID_HI (BCM43xx_CIR_BASE + 0xfc) - -/* Mask to get the Backplane Flag Number from SBTPSFLAG. */ -#define BCM43xx_BACKPLANE_FLAG_NR_MASK 0x3f - -/* SBIMCONFIGLOW values/masks. */ -#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK 0x00000007 -#define BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT 0 -#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK 0x00000070 -#define BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT 4 -#define BCM43xx_SBIMCONFIGLOW_CONNID_MASK 0x00ff0000 -#define BCM43xx_SBIMCONFIGLOW_CONNID_SHIFT 16 - -/* sbtmstatelow state flags */ -#define BCM43xx_SBTMSTATELOW_RESET 0x01 -#define BCM43xx_SBTMSTATELOW_REJECT 0x02 -#define BCM43xx_SBTMSTATELOW_CLOCK 0x10000 -#define BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK 0x20000 -#define BCM43xx_SBTMSTATELOW_G_MODE_ENABLE 0x20000000 - -/* sbtmstatehigh state flags */ -#define BCM43xx_SBTMSTATEHIGH_SERROR 0x00000001 -#define BCM43xx_SBTMSTATEHIGH_BUSY 0x00000004 -#define BCM43xx_SBTMSTATEHIGH_TIMEOUT 0x00000020 -#define BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL 0x00010000 -#define BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL 0x00020000 -#define BCM43xx_SBTMSTATEHIGH_COREFLAGS 0x1FFF0000 -#define BCM43xx_SBTMSTATEHIGH_DMA64BIT 0x10000000 -#define BCM43xx_SBTMSTATEHIGH_GATEDCLK 0x20000000 -#define BCM43xx_SBTMSTATEHIGH_BISTFAILED 0x40000000 -#define BCM43xx_SBTMSTATEHIGH_BISTCOMPLETE 0x80000000 - -/* sbimstate flags */ -#define BCM43xx_SBIMSTATE_IB_ERROR 0x20000 -#define BCM43xx_SBIMSTATE_TIMEOUT 0x40000 - -/* PHYVersioning */ -#define BCM43xx_PHYTYPE_A 0x00 -#define BCM43xx_PHYTYPE_B 0x01 -#define BCM43xx_PHYTYPE_G 0x02 - -/* PHYRegisters */ -#define BCM43xx_PHY_ILT_A_CTRL 0x0072 -#define BCM43xx_PHY_ILT_A_DATA1 0x0073 -#define BCM43xx_PHY_ILT_A_DATA2 0x0074 -#define BCM43xx_PHY_G_LO_CONTROL 0x0810 -#define BCM43xx_PHY_ILT_G_CTRL 0x0472 -#define BCM43xx_PHY_ILT_G_DATA1 0x0473 -#define BCM43xx_PHY_ILT_G_DATA2 0x0474 -#define BCM43xx_PHY_A_PCTL 0x007B -#define BCM43xx_PHY_G_PCTL 0x0029 -#define BCM43xx_PHY_A_CRS 0x0029 -#define BCM43xx_PHY_RADIO_BITFIELD 0x0401 -#define BCM43xx_PHY_G_CRS 0x0429 -#define BCM43xx_PHY_NRSSILT_CTRL 0x0803 -#define BCM43xx_PHY_NRSSILT_DATA 0x0804 - -/* RadioRegisters */ -#define BCM43xx_RADIOCTL_ID 0x01 - -/* StatusBitField */ -#define BCM43xx_SBF_MAC_ENABLED 0x00000001 -#define BCM43xx_SBF_2 0x00000002 /*FIXME: fix name*/ -#define BCM43xx_SBF_CORE_READY 0x00000004 -#define BCM43xx_SBF_400 0x00000400 /*FIXME: fix name*/ -#define BCM43xx_SBF_4000 0x00004000 /*FIXME: fix name*/ -#define BCM43xx_SBF_8000 0x00008000 /*FIXME: fix name*/ -#define BCM43xx_SBF_XFER_REG_BYTESWAP 0x00010000 -#define BCM43xx_SBF_MODE_NOTADHOC 0x00020000 -#define BCM43xx_SBF_MODE_AP 0x00040000 -#define BCM43xx_SBF_RADIOREG_LOCK 0x00080000 -#define BCM43xx_SBF_MODE_MONITOR 0x00400000 -#define BCM43xx_SBF_MODE_PROMISC 0x01000000 -#define BCM43xx_SBF_PS1 0x02000000 -#define BCM43xx_SBF_PS2 0x04000000 -#define BCM43xx_SBF_NO_SSID_BCAST 0x08000000 -#define BCM43xx_SBF_TIME_UPDATE 0x10000000 -#define BCM43xx_SBF_MODE_G 0x80000000 - -/* Microcode */ -#define BCM43xx_UCODE_REVISION 0x0000 -#define BCM43xx_UCODE_PATCHLEVEL 0x0002 -#define BCM43xx_UCODE_DATE 0x0004 -#define BCM43xx_UCODE_TIME 0x0006 -#define BCM43xx_UCODE_STATUS 0x0040 - -/* MicrocodeFlagsBitfield (addr + lo-word values?)*/ -#define BCM43xx_UCODEFLAGS_OFFSET 0x005E - -#define BCM43xx_UCODEFLAG_AUTODIV 0x0001 -#define BCM43xx_UCODEFLAG_UNKBGPHY 0x0002 -#define BCM43xx_UCODEFLAG_UNKBPHY 0x0004 -#define BCM43xx_UCODEFLAG_UNKGPHY 0x0020 -#define BCM43xx_UCODEFLAG_UNKPACTRL 0x0040 -#define BCM43xx_UCODEFLAG_JAPAN 0x0080 - -/* Hardware Radio Enable masks */ -#define BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK (1 << 16) -#define BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK (1 << 4) - -/* Generic-Interrupt reasons. */ -#define BCM43xx_IRQ_READY (1 << 0) -#define BCM43xx_IRQ_BEACON (1 << 1) -#define BCM43xx_IRQ_PS (1 << 2) -#define BCM43xx_IRQ_REG124 (1 << 5) -#define BCM43xx_IRQ_PMQ (1 << 6) -#define BCM43xx_IRQ_PIO_WORKAROUND (1 << 8) -#define BCM43xx_IRQ_XMIT_ERROR (1 << 11) -#define BCM43xx_IRQ_RX (1 << 15) -#define BCM43xx_IRQ_SCAN (1 << 16) -#define BCM43xx_IRQ_NOISE (1 << 18) -#define BCM43xx_IRQ_XMIT_STATUS (1 << 29) - -#define BCM43xx_IRQ_ALL 0xffffffff -#define BCM43xx_IRQ_INITIAL (BCM43xx_IRQ_PS | \ - BCM43xx_IRQ_REG124 | \ - BCM43xx_IRQ_PMQ | \ - BCM43xx_IRQ_XMIT_ERROR | \ - BCM43xx_IRQ_RX | \ - BCM43xx_IRQ_SCAN | \ - BCM43xx_IRQ_NOISE | \ - BCM43xx_IRQ_XMIT_STATUS) - - -/* Initial default iw_mode */ -#define BCM43xx_INITIAL_IWMODE IW_MODE_INFRA - -/* Bus type PCI. */ -#define BCM43xx_BUSTYPE_PCI 0 -/* Bus type Silicone Backplane Bus. */ -#define BCM43xx_BUSTYPE_SB 1 -/* Bus type PCMCIA. */ -#define BCM43xx_BUSTYPE_PCMCIA 2 - -/* Threshold values. */ -#define BCM43xx_MIN_RTS_THRESHOLD 1U -#define BCM43xx_MAX_RTS_THRESHOLD 2304U -#define BCM43xx_DEFAULT_RTS_THRESHOLD BCM43xx_MAX_RTS_THRESHOLD - -#define BCM43xx_DEFAULT_SHORT_RETRY_LIMIT 7 -#define BCM43xx_DEFAULT_LONG_RETRY_LIMIT 4 - -/* FIXME: the next line is a guess as to what the maximum RSSI value might be */ -#define RX_RSSI_MAX 60 - -/* Max size of a security key */ -#define BCM43xx_SEC_KEYSIZE 16 -/* Security algorithms. */ -enum { - BCM43xx_SEC_ALGO_NONE = 0, /* unencrypted, as of TX header. */ - BCM43xx_SEC_ALGO_WEP, - BCM43xx_SEC_ALGO_UNKNOWN, - BCM43xx_SEC_ALGO_AES, - BCM43xx_SEC_ALGO_WEP104, - BCM43xx_SEC_ALGO_TKIP, -}; - -#ifdef assert -# undef assert -#endif -#ifdef CONFIG_BCM43XX_DEBUG -#define assert(expr) \ - do { \ - if (unlikely(!(expr))) { \ - printk(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", \ - #expr, __FILE__, __LINE__, __FUNCTION__); \ - } \ - } while (0) -#else -#define assert(expr) do { /* nothing */ } while (0) -#endif - -/* rate limited printk(). */ -#ifdef printkl -# undef printkl -#endif -#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0) -/* rate limited printk() for debugging */ -#ifdef dprintkl -# undef dprintkl -#endif -#ifdef CONFIG_BCM43XX_DEBUG -# define dprintkl printkl -#else -# define dprintkl(f, x...) do { /* nothing */ } while (0) -#endif - -/* Helper macro for if branches. - * An if branch marked with this macro is only taken in DEBUG mode. - * Example: - * if (DEBUG_ONLY(foo == bar)) { - * do something - * } - * In DEBUG mode, the branch will be taken if (foo == bar). - * In non-DEBUG mode, the branch will never be taken. - */ -#ifdef DEBUG_ONLY -# undef DEBUG_ONLY -#endif -#ifdef CONFIG_BCM43XX_DEBUG -# define DEBUG_ONLY(x) (x) -#else -# define DEBUG_ONLY(x) 0 -#endif - -/* debugging printk() */ -#ifdef dprintk -# undef dprintk -#endif -#ifdef CONFIG_BCM43XX_DEBUG -# define dprintk(f, x...) do { printk(f ,##x); } while (0) -#else -# define dprintk(f, x...) do { /* nothing */ } while (0) -#endif - - -struct net_device; -struct pci_dev; -struct bcm43xx_dmaring; -struct bcm43xx_pioqueue; - -struct bcm43xx_initval { - __be16 offset; - __be16 size; - __be32 value; -} __attribute__((__packed__)); - -/* Values for bcm430x_sprominfo.locale */ -enum { - BCM43xx_LOCALE_WORLD = 0, - BCM43xx_LOCALE_THAILAND, - BCM43xx_LOCALE_ISRAEL, - BCM43xx_LOCALE_JORDAN, - BCM43xx_LOCALE_CHINA, - BCM43xx_LOCALE_JAPAN, - BCM43xx_LOCALE_USA_CANADA_ANZ, - BCM43xx_LOCALE_EUROPE, - BCM43xx_LOCALE_USA_LOW, - BCM43xx_LOCALE_JAPAN_HIGH, - BCM43xx_LOCALE_ALL, - BCM43xx_LOCALE_NONE, -}; - -#define BCM43xx_SPROM_SIZE 64 /* in 16-bit words. */ -struct bcm43xx_sprominfo { - u16 boardflags2; - u8 il0macaddr[6]; - u8 et0macaddr[6]; - u8 et1macaddr[6]; - u8 et0phyaddr:5; - u8 et1phyaddr:5; - u8 boardrev; - u8 locale:4; - u8 antennas_aphy:2; - u8 antennas_bgphy:2; - u16 pa0b0; - u16 pa0b1; - u16 pa0b2; - u8 wl0gpio0; - u8 wl0gpio1; - u8 wl0gpio2; - u8 wl0gpio3; - u8 maxpower_aphy; - u8 maxpower_bgphy; - u16 pa1b0; - u16 pa1b1; - u16 pa1b2; - u8 idle_tssi_tgt_aphy; - u8 idle_tssi_tgt_bgphy; - u16 boardflags; - u16 antennagain_aphy; - u16 antennagain_bgphy; -}; - -/* Value pair to measure the LocalOscillator. */ -struct bcm43xx_lopair { - s8 low; - s8 high; - u8 used:1; -}; -#define BCM43xx_LO_COUNT (14*4) - -struct bcm43xx_phyinfo { - /* Hardware Data */ - u8 analog; - u8 type; - u8 rev; - u16 antenna_diversity; - u16 savedpctlreg; - u16 minlowsig[2]; - u16 minlowsigpos[2]; - u8 connected:1, - calibrated:1, - is_locked:1, /* used in bcm43xx_phy_{un}lock() */ - dyn_tssi_tbl:1; /* used in bcm43xx_phy_init_tssi2dbm_table() */ - /* LO Measurement Data. - * Use bcm43xx_get_lopair() to get a value. - */ - struct bcm43xx_lopair *_lo_pairs; - - /* TSSI to dBm table in use */ - const s8 *tssi2dbm; - /* idle TSSI value */ - s8 idle_tssi; - - /* Values from bcm43xx_calc_loopback_gain() */ - u16 loopback_gain[2]; - - /* PHY lock for core.rev < 3 - * This lock is only used by bcm43xx_phy_{un}lock() - */ - spinlock_t lock; - - /* Firmware. */ - const struct firmware *ucode; - const struct firmware *pcm; - const struct firmware *initvals0; - const struct firmware *initvals1; -}; - - -struct bcm43xx_radioinfo { - u16 manufact; - u16 version; - u8 revision; - - /* Desired TX power in dBm Q5.2 */ - u16 txpower_desired; - /* TX Power control values. */ - union { - /* B/G PHY */ - struct { - u16 baseband_atten; - u16 radio_atten; - u16 txctl1; - u16 txctl2; - }; - /* A PHY */ - struct { - u16 txpwr_offset; - }; - }; - - /* Current Interference Mitigation mode */ - int interfmode; - /* Stack of saved values from the Interference Mitigation code. - * Each value in the stack is layed out as follows: - * bit 0-11: offset - * bit 12-15: register ID - * bit 16-32: value - * register ID is: 0x1 PHY, 0x2 Radio, 0x3 ILT - */ -#define BCM43xx_INTERFSTACK_SIZE 26 - u32 interfstack[BCM43xx_INTERFSTACK_SIZE]; - - /* Saved values from the NRSSI Slope calculation */ - s16 nrssi[2]; - s32 nrssislope; - /* In memory nrssi lookup table. */ - s8 nrssi_lt[64]; - - /* current channel */ - u8 channel; - u8 initial_channel; - - u16 lofcal; - - u16 initval; - - u8 enabled:1; - /* ACI (adjacent channel interference) flags. */ - u8 aci_enable:1, - aci_wlan_automatic:1, - aci_hw_rssi:1; -}; - -/* Data structures for DMA transmission, per 80211 core. */ -struct bcm43xx_dma { - struct bcm43xx_dmaring *tx_ring0; - struct bcm43xx_dmaring *tx_ring1; - struct bcm43xx_dmaring *tx_ring2; - struct bcm43xx_dmaring *tx_ring3; - struct bcm43xx_dmaring *tx_ring4; - struct bcm43xx_dmaring *tx_ring5; - - struct bcm43xx_dmaring *rx_ring0; - struct bcm43xx_dmaring *rx_ring3; /* only available on core.rev < 5 */ -}; - -/* Data structures for PIO transmission, per 80211 core. */ -struct bcm43xx_pio { - struct bcm43xx_pioqueue *queue0; - struct bcm43xx_pioqueue *queue1; - struct bcm43xx_pioqueue *queue2; - struct bcm43xx_pioqueue *queue3; -}; - -#define BCM43xx_MAX_80211_CORES 2 - -/* Generic information about a core. */ -struct bcm43xx_coreinfo { - u8 available:1, - enabled:1, - initialized:1; - /** core_rev revision number */ - u8 rev; - /** Index number for _switch_core() */ - u8 index; - /** core_id ID number */ - u16 id; - /** Core-specific data. */ - void *priv; -}; - -/* Additional information for each 80211 core. */ -struct bcm43xx_coreinfo_80211 { - /* PHY device. */ - struct bcm43xx_phyinfo phy; - /* Radio device. */ - struct bcm43xx_radioinfo radio; - union { - /* DMA context. */ - struct bcm43xx_dma dma; - /* PIO context. */ - struct bcm43xx_pio pio; - }; -}; - -/* Context information for a noise calculation (Link Quality). */ -struct bcm43xx_noise_calculation { - struct bcm43xx_coreinfo *core_at_start; - u8 channel_at_start; - u8 calculation_running:1; - u8 nr_samples; - s8 samples[8][4]; -}; - -struct bcm43xx_stats { - u8 noise; - struct iw_statistics wstats; - /* Store the last TX/RX times here for updating the leds. */ - unsigned long last_tx; - unsigned long last_rx; -}; - -struct bcm43xx_key { - u8 enabled:1; - u8 algorithm; -}; - -/* Driver initialization status. */ -enum { - BCM43xx_STAT_UNINIT, /* Uninitialized. */ - BCM43xx_STAT_INITIALIZING, /* init_board() in progress. */ - BCM43xx_STAT_INITIALIZED, /* Fully operational. */ - BCM43xx_STAT_SHUTTINGDOWN, /* free_board() in progress. */ - BCM43xx_STAT_RESTARTING, /* controller_restart() called. */ -}; -#define bcm43xx_status(bcm) atomic_read(&(bcm)->init_status) -#define bcm43xx_set_status(bcm, stat) do { \ - atomic_set(&(bcm)->init_status, (stat)); \ - smp_wmb(); \ - } while (0) - -/* *** THEORY OF LOCKING *** - * - * We have two different locks in the bcm43xx driver. - * => bcm->mutex: General sleeping mutex. Protects struct bcm43xx_private - * and the device registers. This mutex does _not_ protect - * against concurrency from the IRQ handler. - * => bcm->irq_lock: IRQ spinlock. Protects against IRQ handler concurrency. - * - * Please note that, if you only take the irq_lock, you are not protected - * against concurrency from the periodic work handlers. - * Most times you want to take _both_ locks. - */ - -struct bcm43xx_private { - struct ieee80211_device *ieee; - struct ieee80211softmac_device *softmac; - - struct net_device *net_dev; - struct pci_dev *pci_dev; - unsigned int irq; - - void __iomem *mmio_addr; - - spinlock_t irq_lock; - struct mutex mutex; - - /* Driver initialization status BCM43xx_STAT_*** */ - atomic_t init_status; - - u16 was_initialized:1, /* for PCI suspend/resume. */ - __using_pio:1, /* Internal, use bcm43xx_using_pio(). */ - bad_frames_preempt:1, /* Use "Bad Frames Preemption" (default off) */ - reg124_set_0x4:1, /* Some variable to keep track of IRQ stuff. */ - short_preamble:1, /* TRUE, if short preamble is enabled. */ - firmware_norelease:1, /* Do not release the firmware. Used on suspend. */ - radio_hw_enable:1; /* TRUE if radio is hardware enabled */ - - struct bcm43xx_stats stats; - - /* Bus type we are connected to. - * This is currently always BCM43xx_BUSTYPE_PCI - */ - u8 bustype; - u64 dma_mask; - - u16 board_vendor; - u16 board_type; - u16 board_revision; - - u16 chip_id; - u8 chip_rev; - u8 chip_package; - - struct bcm43xx_sprominfo sprom; -#define BCM43xx_NR_LEDS 4 - struct bcm43xx_led leds[BCM43xx_NR_LEDS]; - spinlock_t leds_lock; - - /* The currently active core. */ - struct bcm43xx_coreinfo *current_core; - struct bcm43xx_coreinfo *active_80211_core; - /* coreinfo structs for all possible cores follow. - * Note that a core might not exist. - * So check the coreinfo flags before using it. - */ - struct bcm43xx_coreinfo core_chipcommon; - struct bcm43xx_coreinfo core_pci; - struct bcm43xx_coreinfo core_80211[ BCM43xx_MAX_80211_CORES ]; - /* Additional information, specific to the 80211 cores. */ - struct bcm43xx_coreinfo_80211 core_80211_ext[ BCM43xx_MAX_80211_CORES ]; - /* Number of available 80211 cores. */ - int nr_80211_available; - - u32 chipcommon_capabilities; - - /* Reason code of the last interrupt. */ - u32 irq_reason; - u32 dma_reason[6]; - /* saved irq enable/disable state bitfield. */ - u32 irq_savedstate; - /* Link Quality calculation context. */ - struct bcm43xx_noise_calculation noisecalc; - /* if > 0 MAC is suspended. if == 0 MAC is enabled. */ - int mac_suspended; - - /* Threshold values. */ - //TODO: The RTS thr has to be _used_. Currently, it is only set via WX. - u32 rts_threshold; - - /* Interrupt Service Routine tasklet (bottom-half) */ - struct tasklet_struct isr_tasklet; - - /* Periodic tasks */ - struct delayed_work periodic_work; - unsigned int periodic_state; - - struct work_struct restart_work; - - /* Informational stuff. */ - char nick[IW_ESSID_MAX_SIZE + 1]; - - /* encryption/decryption */ - u16 security_offset; - struct bcm43xx_key key[54]; - u8 default_key_idx; - - /* Random Number Generator. */ - struct hwrng rng; - char rng_name[20 + 1]; - - /* Debugging stuff follows. */ -#ifdef CONFIG_BCM43XX_DEBUG - struct bcm43xx_dfsentry *dfsentry; -#endif -}; - - -static inline -struct bcm43xx_private * bcm43xx_priv(struct net_device *dev) -{ - return ieee80211softmac_priv(dev); -} - -struct device; - -static inline -struct bcm43xx_private * dev_to_bcm(struct device *dev) -{ - struct net_device *net_dev; - struct bcm43xx_private *bcm; - - net_dev = dev_get_drvdata(dev); - bcm = bcm43xx_priv(net_dev); - - return bcm; -} - - -/* Helper function, which returns a boolean. - * TRUE, if PIO is used; FALSE, if DMA is used. - */ -#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) -static inline -int bcm43xx_using_pio(struct bcm43xx_private *bcm) -{ - return bcm->__using_pio; -} -#elif defined(CONFIG_BCM43XX_DMA) -static inline -int bcm43xx_using_pio(struct bcm43xx_private *bcm) -{ - return 0; -} -#elif defined(CONFIG_BCM43XX_PIO) -static inline -int bcm43xx_using_pio(struct bcm43xx_private *bcm) -{ - return 1; -} -#else -# error "Using neither DMA nor PIO? Confused..." -#endif - -/* Helper functions to access data structures private to the 80211 cores. - * Note that we _must_ have an 80211 core mapped when calling - * any of these functions. - */ -static inline -struct bcm43xx_coreinfo_80211 * -bcm43xx_current_80211_priv(struct bcm43xx_private *bcm) -{ - assert(bcm->current_core->id == BCM43xx_COREID_80211); - return bcm->current_core->priv; -} -static inline -struct bcm43xx_pio * bcm43xx_current_pio(struct bcm43xx_private *bcm) -{ - assert(bcm43xx_using_pio(bcm)); - return &(bcm43xx_current_80211_priv(bcm)->pio); -} -static inline -struct bcm43xx_dma * bcm43xx_current_dma(struct bcm43xx_private *bcm) -{ - assert(!bcm43xx_using_pio(bcm)); - return &(bcm43xx_current_80211_priv(bcm)->dma); -} -static inline -struct bcm43xx_phyinfo * bcm43xx_current_phy(struct bcm43xx_private *bcm) -{ - return &(bcm43xx_current_80211_priv(bcm)->phy); -} -static inline -struct bcm43xx_radioinfo * bcm43xx_current_radio(struct bcm43xx_private *bcm) -{ - return &(bcm43xx_current_80211_priv(bcm)->radio); -} - - -static inline -struct bcm43xx_lopair * bcm43xx_get_lopair(struct bcm43xx_phyinfo *phy, - u16 radio_attenuation, - u16 baseband_attenuation) -{ - return phy->_lo_pairs + (radio_attenuation + 14 * (baseband_attenuation / 2)); -} - - -static inline -u16 bcm43xx_read16(struct bcm43xx_private *bcm, u16 offset) -{ - return ioread16(bcm->mmio_addr + offset); -} - -static inline -void bcm43xx_write16(struct bcm43xx_private *bcm, u16 offset, u16 value) -{ - iowrite16(value, bcm->mmio_addr + offset); -} - -static inline -u32 bcm43xx_read32(struct bcm43xx_private *bcm, u16 offset) -{ - return ioread32(bcm->mmio_addr + offset); -} - -static inline -void bcm43xx_write32(struct bcm43xx_private *bcm, u16 offset, u32 value) -{ - iowrite32(value, bcm->mmio_addr + offset); -} - -static inline -int bcm43xx_pci_read_config16(struct bcm43xx_private *bcm, int offset, u16 *value) -{ - return pci_read_config_word(bcm->pci_dev, offset, value); -} - -static inline -int bcm43xx_pci_read_config32(struct bcm43xx_private *bcm, int offset, u32 *value) -{ - return pci_read_config_dword(bcm->pci_dev, offset, value); -} - -static inline -int bcm43xx_pci_write_config16(struct bcm43xx_private *bcm, int offset, u16 value) -{ - return pci_write_config_word(bcm->pci_dev, offset, value); -} - -static inline -int bcm43xx_pci_write_config32(struct bcm43xx_private *bcm, int offset, u32 value) -{ - return pci_write_config_dword(bcm->pci_dev, offset, value); -} - -/** Limit a value between two limits */ -#ifdef limit_value -# undef limit_value -#endif -#define limit_value(value, min, max) \ - ({ \ - typeof(value) __value = (value); \ - typeof(value) __min = (min); \ - typeof(value) __max = (max); \ - if (__value < __min) \ - __value = __min; \ - else if (__value > __max) \ - __value = __max; \ - __value; \ - }) - -#endif /* BCM43xx_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c deleted file mode 100644 index 76e9dd843faa..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.c +++ /dev/null @@ -1,556 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - debugfs driver debugging code - - Copyright (c) 2005 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - - - -#include -#include -#include -#include -#include -#include - -#include "bcm43xx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_debugfs.h" -#include "bcm43xx_dma.h" -#include "bcm43xx_pio.h" -#include "bcm43xx_xmit.h" - -#define REALLY_BIG_BUFFER_SIZE (1024*256) - -static struct bcm43xx_debugfs fs; -static char really_big_buffer[REALLY_BIG_BUFFER_SIZE]; -static DECLARE_MUTEX(big_buffer_sem); - - -static ssize_t write_file_dummy(struct file *file, const char __user *buf, - size_t count, loff_t *ppos) -{ - return count; -} - -static int open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -#define fappend(fmt, x...) pos += snprintf(buf + pos, len - pos, fmt , ##x) - -static ssize_t devinfo_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - struct net_device *net_dev; - struct pci_dev *pci_dev; - unsigned long flags; - u16 tmp16; - int i; - - down(&big_buffer_sem); - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - fappend("Board not initialized.\n"); - goto out; - } - net_dev = bcm->net_dev; - pci_dev = bcm->pci_dev; - - /* This is where the information is written to the "devinfo" file */ - fappend("*** %s devinfo ***\n", net_dev->name); - fappend("vendor: 0x%04x device: 0x%04x\n", - pci_dev->vendor, pci_dev->device); - fappend("subsystem_vendor: 0x%04x subsystem_device: 0x%04x\n", - pci_dev->subsystem_vendor, pci_dev->subsystem_device); - fappend("IRQ: %d\n", bcm->irq); - fappend("mmio_addr: 0x%p\n", bcm->mmio_addr); - fappend("chip_id: 0x%04x chip_rev: 0x%02x\n", bcm->chip_id, bcm->chip_rev); - if ((bcm->core_80211[0].rev >= 3) && (bcm43xx_read32(bcm, 0x0158) & (1 << 16))) - fappend("Radio disabled by hardware!\n"); - if ((bcm->core_80211[0].rev < 3) && !(bcm43xx_read16(bcm, 0x049A) & (1 << 4))) - fappend("Radio disabled by hardware!\n"); - fappend("board_vendor: 0x%04x board_type: 0x%04x\n", bcm->board_vendor, - bcm->board_type); - - fappend("\nCores:\n"); -#define fappend_core(name, info) fappend("core \"" name "\" %s, %s, id: 0x%04x, " \ - "rev: 0x%02x, index: 0x%02x\n", \ - (info).available \ - ? "available" : "nonavailable", \ - (info).enabled \ - ? "enabled" : "disabled", \ - (info).id, (info).rev, (info).index) - fappend_core("CHIPCOMMON", bcm->core_chipcommon); - fappend_core("PCI", bcm->core_pci); - fappend_core("first 80211", bcm->core_80211[0]); - fappend_core("second 80211", bcm->core_80211[1]); -#undef fappend_core - tmp16 = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - fappend("LEDs: "); - for (i = 0; i < BCM43xx_NR_LEDS; i++) - fappend("%d ", !!(tmp16 & (1 << i))); - fappend("\n"); - -out: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - up(&big_buffer_sem); - return res; -} - -static ssize_t drvinfo_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - - down(&big_buffer_sem); - - /* This is where the information is written to the "driver" file */ - fappend(KBUILD_MODNAME " driver\n"); - fappend("Compiled at: %s %s\n", __DATE__, __TIME__); - - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - up(&big_buffer_sem); - return res; -} - -static ssize_t spromdump_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - unsigned long flags; - - down(&big_buffer_sem); - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - fappend("Board not initialized.\n"); - goto out; - } - - /* This is where the information is written to the "sprom_dump" file */ - fappend("boardflags: 0x%04x\n", bcm->sprom.boardflags); - -out: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - up(&big_buffer_sem); - return res; -} - -static ssize_t tsf_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - unsigned long flags; - u64 tsf; - - down(&big_buffer_sem); - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - fappend("Board not initialized.\n"); - goto out; - } - bcm43xx_tsf_read(bcm, &tsf); - fappend("0x%08x%08x\n", - (unsigned int)((tsf & 0xFFFFFFFF00000000ULL) >> 32), - (unsigned int)(tsf & 0xFFFFFFFFULL)); - -out: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - up(&big_buffer_sem); - return res; -} - -static ssize_t tsf_write_file(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - ssize_t buf_size; - ssize_t res; - unsigned long flags; - unsigned long long tsf; - - buf_size = min(count, sizeof (really_big_buffer) - 1); - down(&big_buffer_sem); - if (copy_from_user(buf, user_buf, buf_size)) { - res = -EFAULT; - goto out_up; - } - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); - res = -EFAULT; - goto out_unlock; - } - if (sscanf(buf, "%lli", &tsf) != 1) { - printk(KERN_INFO PFX "debugfs: invalid values for \"tsf\"\n"); - res = -EINVAL; - goto out_unlock; - } - bcm43xx_tsf_write(bcm, tsf); - mmiowb(); - res = buf_size; - -out_unlock: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -out_up: - up(&big_buffer_sem); - return res; -} - -static ssize_t txstat_read_file(struct file *file, char __user *userbuf, - size_t count, loff_t *ppos) -{ - const size_t len = REALLY_BIG_BUFFER_SIZE; - - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - size_t pos = 0; - ssize_t res; - unsigned long flags; - struct bcm43xx_dfsentry *e; - struct bcm43xx_xmitstatus *status; - int i, cnt, j = 0; - - down(&big_buffer_sem); - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - fappend("Last %d logged xmitstatus blobs (Latest first):\n\n", - BCM43xx_NR_LOGGED_XMITSTATUS); - e = bcm->dfsentry; - if (e->xmitstatus_printing == 0) { - /* At the beginning, make a copy of all data to avoid - * concurrency, as this function is called multiple - * times for big logs. Without copying, the data might - * change between reads. This would result in total trash. - */ - e->xmitstatus_printing = 1; - e->saved_xmitstatus_ptr = e->xmitstatus_ptr; - e->saved_xmitstatus_cnt = e->xmitstatus_cnt; - memcpy(e->xmitstatus_print_buffer, e->xmitstatus_buffer, - BCM43xx_NR_LOGGED_XMITSTATUS * sizeof(*(e->xmitstatus_buffer))); - } - i = e->saved_xmitstatus_ptr - 1; - if (i < 0) - i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; - cnt = e->saved_xmitstatus_cnt; - while (cnt) { - status = e->xmitstatus_print_buffer + i; - fappend("0x%02x: cookie: 0x%04x, flags: 0x%02x, " - "cnt1: 0x%02x, cnt2: 0x%02x, seq: 0x%04x, " - "unk: 0x%04x\n", j, - status->cookie, status->flags, - status->cnt1, status->cnt2, status->seq, - status->unknown); - j++; - cnt--; - i--; - if (i < 0) - i = BCM43xx_NR_LOGGED_XMITSTATUS - 1; - } - - spin_unlock_irqrestore(&bcm->irq_lock, flags); - res = simple_read_from_buffer(userbuf, count, ppos, buf, pos); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (*ppos == pos) { - /* Done. Drop the copied data. */ - e->xmitstatus_printing = 0; - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - up(&big_buffer_sem); - return res; -} - -static ssize_t restart_write_file(struct file *file, const char __user *user_buf, - size_t count, loff_t *ppos) -{ - struct bcm43xx_private *bcm = file->private_data; - char *buf = really_big_buffer; - ssize_t buf_size; - ssize_t res; - unsigned long flags; - - buf_size = min(count, sizeof (really_big_buffer) - 1); - down(&big_buffer_sem); - if (copy_from_user(buf, user_buf, buf_size)) { - res = -EFAULT; - goto out_up; - } - mutex_lock(&(bcm)->mutex); - spin_lock_irqsave(&(bcm)->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) { - printk(KERN_INFO PFX "debugfs: Board not initialized.\n"); - res = -EFAULT; - goto out_unlock; - } - if (count > 0 && buf[0] == '1') { - bcm43xx_controller_restart(bcm, "manually restarted"); - res = count; - } else - res = -EINVAL; - -out_unlock: - spin_unlock_irqrestore(&(bcm)->irq_lock, flags); - mutex_unlock(&(bcm)->mutex); -out_up: - up(&big_buffer_sem); - return res; -} - -#undef fappend - - -static const struct file_operations devinfo_fops = { - .read = devinfo_read_file, - .write = write_file_dummy, - .open = open_file_generic, -}; - -static const struct file_operations spromdump_fops = { - .read = spromdump_read_file, - .write = write_file_dummy, - .open = open_file_generic, -}; - -static const struct file_operations drvinfo_fops = { - .read = drvinfo_read_file, - .write = write_file_dummy, - .open = open_file_generic, -}; - -static const struct file_operations tsf_fops = { - .read = tsf_read_file, - .write = tsf_write_file, - .open = open_file_generic, -}; - -static const struct file_operations txstat_fops = { - .read = txstat_read_file, - .write = write_file_dummy, - .open = open_file_generic, -}; - -static const struct file_operations restart_fops = { - .write = restart_write_file, - .open = open_file_generic, -}; - - -void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) -{ - struct bcm43xx_dfsentry *e; - char devdir[IFNAMSIZ]; - - assert(bcm); - e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) { - printk(KERN_ERR PFX "out of memory\n"); - return; - } - e->bcm = bcm; - e->xmitstatus_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS - * sizeof(*(e->xmitstatus_buffer)), - GFP_KERNEL); - if (!e->xmitstatus_buffer) { - printk(KERN_ERR PFX "out of memory\n"); - kfree(e); - return; - } - e->xmitstatus_print_buffer = kzalloc(BCM43xx_NR_LOGGED_XMITSTATUS - * sizeof(*(e->xmitstatus_buffer)), - GFP_KERNEL); - if (!e->xmitstatus_print_buffer) { - printk(KERN_ERR PFX "out of memory\n"); - kfree(e); - return; - } - - - bcm->dfsentry = e; - - strncpy(devdir, bcm->net_dev->name, ARRAY_SIZE(devdir)); - e->subdir = debugfs_create_dir(devdir, fs.root); - e->dentry_devinfo = debugfs_create_file("devinfo", 0444, e->subdir, - bcm, &devinfo_fops); - if (!e->dentry_devinfo) - printk(KERN_ERR PFX "debugfs: creating \"devinfo\" for \"%s\" failed!\n", devdir); - e->dentry_spromdump = debugfs_create_file("sprom_dump", 0444, e->subdir, - bcm, &spromdump_fops); - if (!e->dentry_spromdump) - printk(KERN_ERR PFX "debugfs: creating \"sprom_dump\" for \"%s\" failed!\n", devdir); - e->dentry_tsf = debugfs_create_file("tsf", 0666, e->subdir, - bcm, &tsf_fops); - if (!e->dentry_tsf) - printk(KERN_ERR PFX "debugfs: creating \"tsf\" for \"%s\" failed!\n", devdir); - e->dentry_txstat = debugfs_create_file("tx_status", 0444, e->subdir, - bcm, &txstat_fops); - if (!e->dentry_txstat) - printk(KERN_ERR PFX "debugfs: creating \"tx_status\" for \"%s\" failed!\n", devdir); - e->dentry_restart = debugfs_create_file("restart", 0222, e->subdir, - bcm, &restart_fops); - if (!e->dentry_restart) - printk(KERN_ERR PFX "debugfs: creating \"restart\" for \"%s\" failed!\n", devdir); -} - -void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) -{ - struct bcm43xx_dfsentry *e; - - if (!bcm) - return; - - e = bcm->dfsentry; - assert(e); - debugfs_remove(e->dentry_spromdump); - debugfs_remove(e->dentry_devinfo); - debugfs_remove(e->dentry_tsf); - debugfs_remove(e->dentry_txstat); - debugfs_remove(e->dentry_restart); - debugfs_remove(e->subdir); - kfree(e->xmitstatus_buffer); - kfree(e->xmitstatus_print_buffer); - kfree(e); -} - -void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ - struct bcm43xx_dfsentry *e; - struct bcm43xx_xmitstatus *savedstatus; - - /* This is protected by bcm->_lock */ - e = bcm->dfsentry; - assert(e); - savedstatus = e->xmitstatus_buffer + e->xmitstatus_ptr; - memcpy(savedstatus, status, sizeof(*status)); - e->xmitstatus_ptr++; - if (e->xmitstatus_ptr >= BCM43xx_NR_LOGGED_XMITSTATUS) - e->xmitstatus_ptr = 0; - if (e->xmitstatus_cnt < BCM43xx_NR_LOGGED_XMITSTATUS) - e->xmitstatus_cnt++; -} - -void bcm43xx_debugfs_init(void) -{ - memset(&fs, 0, sizeof(fs)); - fs.root = debugfs_create_dir(KBUILD_MODNAME, NULL); - if (!fs.root) - printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "\" subdir failed!\n"); - fs.dentry_driverinfo = debugfs_create_file("driver", 0444, fs.root, NULL, &drvinfo_fops); - if (!fs.dentry_driverinfo) - printk(KERN_ERR PFX "debugfs: creating \"" KBUILD_MODNAME "/driver\" failed!\n"); -} - -void bcm43xx_debugfs_exit(void) -{ - debugfs_remove(fs.dentry_driverinfo); - debugfs_remove(fs.root); -} - -void bcm43xx_printk_dump(const char *data, - size_t size, - const char *description) -{ - size_t i; - char c; - - printk(KERN_INFO PFX "Data dump (%s, %zd bytes):", - description, size); - for (i = 0; i < size; i++) { - c = data[i]; - if (i % 8 == 0) - printk("\n" KERN_INFO PFX "0x%08zx: 0x%02x, ", i, c & 0xff); - else - printk("0x%02x, ", c & 0xff); - } - printk("\n"); -} - -void bcm43xx_printk_bitdump(const unsigned char *data, - size_t bytes, int msb_to_lsb, - const char *description) -{ - size_t i; - int j; - const unsigned char *d; - - printk(KERN_INFO PFX "*** Bitdump (%s, %zd bytes, %s) ***", - description, bytes, msb_to_lsb ? "MSB to LSB" : "LSB to MSB"); - for (i = 0; i < bytes; i++) { - d = data + i; - if (i % 8 == 0) - printk("\n" KERN_INFO PFX "0x%08zx: ", i); - if (msb_to_lsb) { - for (j = 7; j >= 0; j--) { - if (*d & (1 << j)) - printk("1"); - else - printk("0"); - } - } else { - for (j = 0; j < 8; j++) { - if (*d & (1 << j)) - printk("1"); - else - printk("0"); - } - } - printk(" "); - } - printk("\n"); -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h deleted file mode 100644 index a40d1af35545..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_debugfs.h +++ /dev/null @@ -1,118 +0,0 @@ -#ifndef BCM43xx_DEBUGFS_H_ -#define BCM43xx_DEBUGFS_H_ - -struct bcm43xx_private; -struct bcm43xx_xmitstatus; - -#ifdef CONFIG_BCM43XX_DEBUG - -#include -#include - -struct dentry; - -/* limited by the size of the "really_big_buffer" */ -#define BCM43xx_NR_LOGGED_XMITSTATUS 100 - -struct bcm43xx_dfsentry { - struct dentry *subdir; - struct dentry *dentry_devinfo; - struct dentry *dentry_spromdump; - struct dentry *dentry_tsf; - struct dentry *dentry_txstat; - struct dentry *dentry_restart; - - struct bcm43xx_private *bcm; - - /* saved xmitstatus. */ - struct bcm43xx_xmitstatus *xmitstatus_buffer; - int xmitstatus_ptr; - int xmitstatus_cnt; - /* We need a seperate buffer while printing to avoid - * concurrency issues. (New xmitstatus can arrive - * while we are printing). - */ - struct bcm43xx_xmitstatus *xmitstatus_print_buffer; - int saved_xmitstatus_ptr; - int saved_xmitstatus_cnt; - int xmitstatus_printing; -}; - -struct bcm43xx_debugfs { - struct dentry *root; - struct dentry *dentry_driverinfo; -}; - -void bcm43xx_debugfs_init(void); -void bcm43xx_debugfs_exit(void); -void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm); -void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm); -void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status); - -/* Debug helper: Dump binary data through printk. */ -void bcm43xx_printk_dump(const char *data, - size_t size, - const char *description); -/* Debug helper: Dump bitwise binary data through printk. */ -void bcm43xx_printk_bitdump(const unsigned char *data, - size_t bytes, int msb_to_lsb, - const char *description); -#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) \ - do { \ - bcm43xx_printk_bitdump((const unsigned char *)(pointer), \ - sizeof(*(pointer)), \ - (msb_to_lsb), \ - (description)); \ - } while (0) - -#else /* CONFIG_BCM43XX_DEBUG*/ - -static inline -void bcm43xx_debugfs_init(void) { } -static inline -void bcm43xx_debugfs_exit(void) { } -static inline -void bcm43xx_debugfs_add_device(struct bcm43xx_private *bcm) { } -static inline -void bcm43xx_debugfs_remove_device(struct bcm43xx_private *bcm) { } -static inline -void bcm43xx_debugfs_log_txstat(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) { } - -static inline -void bcm43xx_printk_dump(const char *data, - size_t size, - const char *description) -{ -} -static inline -void bcm43xx_printk_bitdump(const unsigned char *data, - size_t bytes, int msb_to_lsb, - const char *description) -{ -} -#define bcm43xx_printk_bitdumpt(pointer, msb_to_lsb, description) do { /* nothing */ } while (0) - -#endif /* CONFIG_BCM43XX_DEBUG*/ - -/* Ugly helper macros to make incomplete code more verbose on runtime */ -#ifdef TODO -# undef TODO -#endif -#define TODO() \ - do { \ - printk(KERN_INFO PFX "TODO: Incomplete code in %s() at %s:%d\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - } while (0) - -#ifdef FIXME -# undef FIXME -#endif -#define FIXME() \ - do { \ - printk(KERN_INFO PFX "FIXME: Possibly broken code in %s() at %s:%d\n", \ - __FUNCTION__, __FILE__, __LINE__); \ - } while (0) - -#endif /* BCM43xx_DEBUGFS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c b/drivers/net/wireless/bcm43xx/bcm43xx_dma.c deleted file mode 100644 index 1f7731fcfbd5..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.c +++ /dev/null @@ -1,1263 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - DMA ringbuffer and descriptor allocation/management - - Copyright (c) 2005, 2006 Michael Buesch - - Some code in this file is derived from the b44.c driver - Copyright (C) 2002 David S. Miller - Copyright (C) Pekka Pietikainen - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx.h" -#include "bcm43xx_dma.h" -#include "bcm43xx_main.h" -#include "bcm43xx_debugfs.h" -#include "bcm43xx_power.h" -#include "bcm43xx_xmit.h" - -#include -#include -#include -#include - - -static inline int free_slots(struct bcm43xx_dmaring *ring) -{ - return (ring->nr_slots - ring->used_slots); -} - -static inline int next_slot(struct bcm43xx_dmaring *ring, int slot) -{ - assert(slot >= -1 && slot <= ring->nr_slots - 1); - if (slot == ring->nr_slots - 1) - return 0; - return slot + 1; -} - -static inline int prev_slot(struct bcm43xx_dmaring *ring, int slot) -{ - assert(slot >= 0 && slot <= ring->nr_slots - 1); - if (slot == 0) - return ring->nr_slots - 1; - return slot - 1; -} - -/* Request a slot for usage. */ -static inline -int request_slot(struct bcm43xx_dmaring *ring) -{ - int slot; - - assert(ring->tx); - assert(!ring->suspended); - assert(free_slots(ring) != 0); - - slot = next_slot(ring, ring->current_slot); - ring->current_slot = slot; - ring->used_slots++; - - /* Check the number of available slots and suspend TX, - * if we are running low on free slots. - */ - if (unlikely(free_slots(ring) < ring->suspend_mark)) { - netif_stop_queue(ring->bcm->net_dev); - ring->suspended = 1; - } -#ifdef CONFIG_BCM43XX_DEBUG - if (ring->used_slots > ring->max_used_slots) - ring->max_used_slots = ring->used_slots; -#endif /* CONFIG_BCM43XX_DEBUG*/ - - return slot; -} - -/* Return a slot to the free slots. */ -static inline -void return_slot(struct bcm43xx_dmaring *ring, int slot) -{ - assert(ring->tx); - - ring->used_slots--; - - /* Check if TX is suspended and check if we have - * enough free slots to resume it again. - */ - if (unlikely(ring->suspended)) { - if (free_slots(ring) >= ring->resume_mark) { - ring->suspended = 0; - netif_wake_queue(ring->bcm->net_dev); - } - } -} - -u16 bcm43xx_dmacontroller_base(int dma64bit, int controller_idx) -{ - static const u16 map64[] = { - BCM43xx_MMIO_DMA64_BASE0, - BCM43xx_MMIO_DMA64_BASE1, - BCM43xx_MMIO_DMA64_BASE2, - BCM43xx_MMIO_DMA64_BASE3, - BCM43xx_MMIO_DMA64_BASE4, - BCM43xx_MMIO_DMA64_BASE5, - }; - static const u16 map32[] = { - BCM43xx_MMIO_DMA32_BASE0, - BCM43xx_MMIO_DMA32_BASE1, - BCM43xx_MMIO_DMA32_BASE2, - BCM43xx_MMIO_DMA32_BASE3, - BCM43xx_MMIO_DMA32_BASE4, - BCM43xx_MMIO_DMA32_BASE5, - }; - - if (dma64bit) { - assert(controller_idx >= 0 && - controller_idx < ARRAY_SIZE(map64)); - return map64[controller_idx]; - } - assert(controller_idx >= 0 && - controller_idx < ARRAY_SIZE(map32)); - return map32[controller_idx]; -} - -static inline -dma_addr_t map_descbuffer(struct bcm43xx_dmaring *ring, - unsigned char *buf, - size_t len, - int tx) -{ - dma_addr_t dmaaddr; - int direction = PCI_DMA_FROMDEVICE; - - if (tx) - direction = PCI_DMA_TODEVICE; - - dmaaddr = pci_map_single(ring->bcm->pci_dev, - buf, len, - direction); - - return dmaaddr; -} - -static inline -void unmap_descbuffer(struct bcm43xx_dmaring *ring, - dma_addr_t addr, - size_t len, - int tx) -{ - if (tx) { - pci_unmap_single(ring->bcm->pci_dev, - addr, len, - PCI_DMA_TODEVICE); - } else { - pci_unmap_single(ring->bcm->pci_dev, - addr, len, - PCI_DMA_FROMDEVICE); - } -} - -static inline -void sync_descbuffer_for_cpu(struct bcm43xx_dmaring *ring, - dma_addr_t addr, - size_t len) -{ - assert(!ring->tx); - - pci_dma_sync_single_for_cpu(ring->bcm->pci_dev, - addr, len, PCI_DMA_FROMDEVICE); -} - -static inline -void sync_descbuffer_for_device(struct bcm43xx_dmaring *ring, - dma_addr_t addr, - size_t len) -{ - assert(!ring->tx); - - pci_dma_sync_single_for_cpu(ring->bcm->pci_dev, - addr, len, PCI_DMA_TODEVICE); -} - -/* Unmap and free a descriptor buffer. */ -static inline -void free_descriptor_buffer(struct bcm43xx_dmaring *ring, - struct bcm43xx_dmadesc_meta *meta, - int irq_context) -{ - assert(meta->skb); - if (irq_context) - dev_kfree_skb_irq(meta->skb); - else - dev_kfree_skb(meta->skb); - meta->skb = NULL; -} - -static int alloc_ringmemory(struct bcm43xx_dmaring *ring) -{ - ring->descbase = pci_alloc_consistent(ring->bcm->pci_dev, BCM43xx_DMA_RINGMEMSIZE, - &(ring->dmabase)); - if (!ring->descbase) { - /* Allocation may have failed due to pci_alloc_consistent - insisting on use of GFP_DMA, which is more restrictive - than necessary... */ - struct dma_desc *rx_ring; - dma_addr_t rx_ring_dma; - - rx_ring = kzalloc(BCM43xx_DMA_RINGMEMSIZE, GFP_KERNEL); - if (!rx_ring) - goto out_err; - - rx_ring_dma = pci_map_single(ring->bcm->pci_dev, rx_ring, - BCM43xx_DMA_RINGMEMSIZE, - PCI_DMA_BIDIRECTIONAL); - - if (pci_dma_mapping_error(rx_ring_dma) || - rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) { - /* Sigh... */ - if (!pci_dma_mapping_error(rx_ring_dma)) - pci_unmap_single(ring->bcm->pci_dev, - rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE, - PCI_DMA_BIDIRECTIONAL); - rx_ring_dma = pci_map_single(ring->bcm->pci_dev, - rx_ring, BCM43xx_DMA_RINGMEMSIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(rx_ring_dma) || - rx_ring_dma + BCM43xx_DMA_RINGMEMSIZE > ring->bcm->dma_mask) { - assert(0); - if (!pci_dma_mapping_error(rx_ring_dma)) - pci_unmap_single(ring->bcm->pci_dev, - rx_ring_dma, BCM43xx_DMA_RINGMEMSIZE, - PCI_DMA_BIDIRECTIONAL); - goto out_err; - } - } - - ring->descbase = rx_ring; - ring->dmabase = rx_ring_dma; - } - memset(ring->descbase, 0, BCM43xx_DMA_RINGMEMSIZE); - - return 0; -out_err: - printk(KERN_ERR PFX "DMA ringmemory allocation failed\n"); - return -ENOMEM; -} - -static void free_ringmemory(struct bcm43xx_dmaring *ring) -{ - struct device *dev = &(ring->bcm->pci_dev->dev); - - dma_free_coherent(dev, BCM43xx_DMA_RINGMEMSIZE, - ring->descbase, ring->dmabase); -} - -/* Reset the RX DMA channel */ -int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, - u16 mmio_base, int dma64) -{ - int i; - u32 value; - u16 offset; - - offset = dma64 ? BCM43xx_DMA64_RXCTL : BCM43xx_DMA32_RXCTL; - bcm43xx_write32(bcm, mmio_base + offset, 0); - for (i = 0; i < 1000; i++) { - offset = dma64 ? BCM43xx_DMA64_RXSTATUS : BCM43xx_DMA32_RXSTATUS; - value = bcm43xx_read32(bcm, mmio_base + offset); - if (dma64) { - value &= BCM43xx_DMA64_RXSTAT; - if (value == BCM43xx_DMA64_RXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= BCM43xx_DMA32_RXSTATE; - if (value == BCM43xx_DMA32_RXSTAT_DISABLED) { - i = -1; - break; - } - } - udelay(10); - } - if (i != -1) { - printk(KERN_ERR PFX "Error: Wait on DMA RX status timed out.\n"); - return -ENODEV; - } - - return 0; -} - -/* Reset the RX DMA channel */ -int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, - u16 mmio_base, int dma64) -{ - int i; - u32 value; - u16 offset; - - for (i = 0; i < 1000; i++) { - offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS; - value = bcm43xx_read32(bcm, mmio_base + offset); - if (dma64) { - value &= BCM43xx_DMA64_TXSTAT; - if (value == BCM43xx_DMA64_TXSTAT_DISABLED || - value == BCM43xx_DMA64_TXSTAT_IDLEWAIT || - value == BCM43xx_DMA64_TXSTAT_STOPPED) - break; - } else { - value &= BCM43xx_DMA32_TXSTATE; - if (value == BCM43xx_DMA32_TXSTAT_DISABLED || - value == BCM43xx_DMA32_TXSTAT_IDLEWAIT || - value == BCM43xx_DMA32_TXSTAT_STOPPED) - break; - } - udelay(10); - } - offset = dma64 ? BCM43xx_DMA64_TXCTL : BCM43xx_DMA32_TXCTL; - bcm43xx_write32(bcm, mmio_base + offset, 0); - for (i = 0; i < 1000; i++) { - offset = dma64 ? BCM43xx_DMA64_TXSTATUS : BCM43xx_DMA32_TXSTATUS; - value = bcm43xx_read32(bcm, mmio_base + offset); - if (dma64) { - value &= BCM43xx_DMA64_TXSTAT; - if (value == BCM43xx_DMA64_TXSTAT_DISABLED) { - i = -1; - break; - } - } else { - value &= BCM43xx_DMA32_TXSTATE; - if (value == BCM43xx_DMA32_TXSTAT_DISABLED) { - i = -1; - break; - } - } - udelay(10); - } - if (i != -1) { - printk(KERN_ERR PFX "Error: Wait on DMA TX status timed out.\n"); - return -ENODEV; - } - /* ensure the reset is completed. */ - udelay(300); - - return 0; -} - -static void fill_descriptor(struct bcm43xx_dmaring *ring, - struct bcm43xx_dmadesc_generic *desc, - dma_addr_t dmaaddr, - u16 bufsize, - int start, int end, int irq) -{ - int slot; - - slot = bcm43xx_dma_desc2idx(ring, desc); - assert(slot >= 0 && slot < ring->nr_slots); - - if (ring->dma64) { - u32 ctl0 = 0, ctl1 = 0; - u32 addrlo, addrhi; - u32 addrext; - - addrlo = (u32)(dmaaddr & 0xFFFFFFFF); - addrhi = (((u64)dmaaddr >> 32) & ~BCM43xx_DMA64_ROUTING); - addrext = (((u64)dmaaddr >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); - addrhi |= ring->routing; - if (slot == ring->nr_slots - 1) - ctl0 |= BCM43xx_DMA64_DCTL0_DTABLEEND; - if (start) - ctl0 |= BCM43xx_DMA64_DCTL0_FRAMESTART; - if (end) - ctl0 |= BCM43xx_DMA64_DCTL0_FRAMEEND; - if (irq) - ctl0 |= BCM43xx_DMA64_DCTL0_IRQ; - ctl1 |= (bufsize - ring->frameoffset) - & BCM43xx_DMA64_DCTL1_BYTECNT; - ctl1 |= (addrext << BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT) - & BCM43xx_DMA64_DCTL1_ADDREXT_MASK; - - desc->dma64.control0 = cpu_to_le32(ctl0); - desc->dma64.control1 = cpu_to_le32(ctl1); - desc->dma64.address_low = cpu_to_le32(addrlo); - desc->dma64.address_high = cpu_to_le32(addrhi); - } else { - u32 ctl; - u32 addr; - u32 addrext; - - addr = (u32)(dmaaddr & ~BCM43xx_DMA32_ROUTING); - addrext = (u32)(dmaaddr & BCM43xx_DMA32_ROUTING) - >> BCM43xx_DMA32_ROUTING_SHIFT; - addr |= ring->routing; - ctl = (bufsize - ring->frameoffset) - & BCM43xx_DMA32_DCTL_BYTECNT; - if (slot == ring->nr_slots - 1) - ctl |= BCM43xx_DMA32_DCTL_DTABLEEND; - if (start) - ctl |= BCM43xx_DMA32_DCTL_FRAMESTART; - if (end) - ctl |= BCM43xx_DMA32_DCTL_FRAMEEND; - if (irq) - ctl |= BCM43xx_DMA32_DCTL_IRQ; - ctl |= (addrext << BCM43xx_DMA32_DCTL_ADDREXT_SHIFT) - & BCM43xx_DMA32_DCTL_ADDREXT_MASK; - - desc->dma32.control = cpu_to_le32(ctl); - desc->dma32.address = cpu_to_le32(addr); - } -} - -static int setup_rx_descbuffer(struct bcm43xx_dmaring *ring, - struct bcm43xx_dmadesc_generic *desc, - struct bcm43xx_dmadesc_meta *meta, - gfp_t gfp_flags) -{ - struct bcm43xx_rxhdr *rxhdr; - struct bcm43xx_hwxmitstatus *xmitstat; - dma_addr_t dmaaddr; - struct sk_buff *skb; - - assert(!ring->tx); - - skb = __dev_alloc_skb(ring->rx_buffersize, gfp_flags); - if (unlikely(!skb)) - return -ENOMEM; - dmaaddr = map_descbuffer(ring, skb->data, ring->rx_buffersize, 0); - /* This hardware bug work-around adapted from the b44 driver. - The chip may be unable to do PCI DMA to/from anything above 1GB */ - if (pci_dma_mapping_error(dmaaddr) || - dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) { - /* This one has 30-bit addressing... */ - if (!pci_dma_mapping_error(dmaaddr)) - pci_unmap_single(ring->bcm->pci_dev, - dmaaddr, ring->rx_buffersize, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(skb); - skb = __dev_alloc_skb(ring->rx_buffersize,GFP_DMA); - if (skb == NULL) - return -ENOMEM; - dmaaddr = pci_map_single(ring->bcm->pci_dev, - skb->data, ring->rx_buffersize, - PCI_DMA_FROMDEVICE); - if (pci_dma_mapping_error(dmaaddr) || - dmaaddr + ring->rx_buffersize > ring->bcm->dma_mask) { - assert(0); - dev_kfree_skb_any(skb); - return -ENOMEM; - } - } - meta->skb = skb; - meta->dmaaddr = dmaaddr; - skb->dev = ring->bcm->net_dev; - - fill_descriptor(ring, desc, dmaaddr, - ring->rx_buffersize, 0, 0, 0); - - rxhdr = (struct bcm43xx_rxhdr *)(skb->data); - rxhdr->frame_length = 0; - rxhdr->flags1 = 0; - xmitstat = (struct bcm43xx_hwxmitstatus *)(skb->data); - xmitstat->cookie = 0; - - return 0; -} - -/* Allocate the initial descbuffers. - * This is used for an RX ring only. - */ -static int alloc_initial_descbuffers(struct bcm43xx_dmaring *ring) -{ - int i, err = -ENOMEM; - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - - for (i = 0; i < ring->nr_slots; i++) { - desc = bcm43xx_dma_idx2desc(ring, i, &meta); - - err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); - if (err) - goto err_unwind; - } - mb(); - ring->used_slots = ring->nr_slots; - err = 0; -out: - return err; - -err_unwind: - for (i--; i >= 0; i--) { - desc = bcm43xx_dma_idx2desc(ring, i, &meta); - - unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); - dev_kfree_skb(meta->skb); - } - goto out; -} - -/* Do initial setup of the DMA controller. - * Reset the controller, write the ring busaddress - * and switch the "enable" bit on. - */ -static int dmacontroller_setup(struct bcm43xx_dmaring *ring) -{ - int err = 0; - u32 value; - u32 addrext; - - if (ring->tx) { - if (ring->dma64) { - u64 ringbase = (u64)(ring->dmabase); - - addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); - value = BCM43xx_DMA64_TXENABLE; - value |= (addrext << BCM43xx_DMA64_TXADDREXT_SHIFT) - & BCM43xx_DMA64_TXADDREXT_MASK; - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, value); - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, - (ringbase & 0xFFFFFFFF)); - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, - ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING) - | ring->routing); - } else { - u32 ringbase = (u32)(ring->dmabase); - - addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT); - value = BCM43xx_DMA32_TXENABLE; - value |= (addrext << BCM43xx_DMA32_TXADDREXT_SHIFT) - & BCM43xx_DMA32_TXADDREXT_MASK; - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, value); - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, - (ringbase & ~BCM43xx_DMA32_ROUTING) - | ring->routing); - } - } else { - err = alloc_initial_descbuffers(ring); - if (err) - goto out; - if (ring->dma64) { - u64 ringbase = (u64)(ring->dmabase); - - addrext = ((ringbase >> 32) >> BCM43xx_DMA64_ROUTING_SHIFT); - value = (ring->frameoffset << BCM43xx_DMA64_RXFROFF_SHIFT); - value |= BCM43xx_DMA64_RXENABLE; - value |= (addrext << BCM43xx_DMA64_RXADDREXT_SHIFT) - & BCM43xx_DMA64_RXADDREXT_MASK; - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXCTL, value); - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, - (ringbase & 0xFFFFFFFF)); - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, - ((ringbase >> 32) & ~BCM43xx_DMA64_ROUTING) - | ring->routing); - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, 200); - } else { - u32 ringbase = (u32)(ring->dmabase); - - addrext = (ringbase >> BCM43xx_DMA32_ROUTING_SHIFT); - value = (ring->frameoffset << BCM43xx_DMA32_RXFROFF_SHIFT); - value |= BCM43xx_DMA32_RXENABLE; - value |= (addrext << BCM43xx_DMA32_RXADDREXT_SHIFT) - & BCM43xx_DMA32_RXADDREXT_MASK; - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXCTL, value); - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, - (ringbase & ~BCM43xx_DMA32_ROUTING) - | ring->routing); - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, 200); - } - } - -out: - return err; -} - -/* Shutdown the DMA controller. */ -static void dmacontroller_cleanup(struct bcm43xx_dmaring *ring) -{ - if (ring->tx) { - bcm43xx_dmacontroller_tx_reset(ring->bcm, ring->mmio_base, ring->dma64); - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGLO, 0); - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXRINGHI, 0); - } else - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXRING, 0); - } else { - bcm43xx_dmacontroller_rx_reset(ring->bcm, ring->mmio_base, ring->dma64); - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGLO, 0); - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXRINGHI, 0); - } else - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXRING, 0); - } -} - -static void free_all_descbuffers(struct bcm43xx_dmaring *ring) -{ - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - int i; - - if (!ring->used_slots) - return; - for (i = 0; i < ring->nr_slots; i++) { - desc = bcm43xx_dma_idx2desc(ring, i, &meta); - - if (!meta->skb) { - assert(ring->tx); - continue; - } - if (ring->tx) { - unmap_descbuffer(ring, meta->dmaaddr, - meta->skb->len, 1); - } else { - unmap_descbuffer(ring, meta->dmaaddr, - ring->rx_buffersize, 0); - } - free_descriptor_buffer(ring, meta, 0); - } -} - -/* Main initialization function. */ -static -struct bcm43xx_dmaring * bcm43xx_setup_dmaring(struct bcm43xx_private *bcm, - int controller_index, - int for_tx, - int dma64) -{ - struct bcm43xx_dmaring *ring; - int err; - int nr_slots; - - ring = kzalloc(sizeof(*ring), GFP_KERNEL); - if (!ring) - goto out; - - nr_slots = BCM43xx_RXRING_SLOTS; - if (for_tx) - nr_slots = BCM43xx_TXRING_SLOTS; - - ring->meta = kcalloc(nr_slots, sizeof(struct bcm43xx_dmadesc_meta), - GFP_KERNEL); - if (!ring->meta) - goto err_kfree_ring; - - ring->routing = BCM43xx_DMA32_CLIENTTRANS; - if (dma64) - ring->routing = BCM43xx_DMA64_CLIENTTRANS; - - ring->bcm = bcm; - ring->nr_slots = nr_slots; - ring->suspend_mark = ring->nr_slots * BCM43xx_TXSUSPEND_PERCENT / 100; - ring->resume_mark = ring->nr_slots * BCM43xx_TXRESUME_PERCENT / 100; - assert(ring->suspend_mark < ring->resume_mark); - ring->mmio_base = bcm43xx_dmacontroller_base(dma64, controller_index); - ring->index = controller_index; - ring->dma64 = !!dma64; - if (for_tx) { - ring->tx = 1; - ring->current_slot = -1; - } else { - if (ring->index == 0) { - ring->rx_buffersize = BCM43xx_DMA0_RX_BUFFERSIZE; - ring->frameoffset = BCM43xx_DMA0_RX_FRAMEOFFSET; - } else if (ring->index == 3) { - ring->rx_buffersize = BCM43xx_DMA3_RX_BUFFERSIZE; - ring->frameoffset = BCM43xx_DMA3_RX_FRAMEOFFSET; - } else - assert(0); - } - - err = alloc_ringmemory(ring); - if (err) - goto err_kfree_meta; - err = dmacontroller_setup(ring); - if (err) - goto err_free_ringmemory; - return ring; - -out: - printk(KERN_ERR PFX "Error in bcm43xx_setup_dmaring\n"); - return ring; - -err_free_ringmemory: - free_ringmemory(ring); -err_kfree_meta: - kfree(ring->meta); -err_kfree_ring: - kfree(ring); - ring = NULL; - goto out; -} - -/* Main cleanup function. */ -static void bcm43xx_destroy_dmaring(struct bcm43xx_dmaring *ring) -{ - if (!ring) - return; - - dprintk(KERN_INFO PFX "DMA-%s 0x%04X (%s) max used slots: %d/%d\n", - (ring->dma64) ? "64" : "32", - ring->mmio_base, - (ring->tx) ? "TX" : "RX", - ring->max_used_slots, ring->nr_slots); - /* Device IRQs are disabled prior entering this function, - * so no need to take care of concurrency with rx handler stuff. - */ - dmacontroller_cleanup(ring); - free_all_descbuffers(ring); - free_ringmemory(ring); - - kfree(ring->meta); - kfree(ring); -} - -void bcm43xx_dma_free(struct bcm43xx_private *bcm) -{ - struct bcm43xx_dma *dma; - - if (bcm43xx_using_pio(bcm)) - return; - dma = bcm43xx_current_dma(bcm); - - bcm43xx_destroy_dmaring(dma->rx_ring3); - dma->rx_ring3 = NULL; - bcm43xx_destroy_dmaring(dma->rx_ring0); - dma->rx_ring0 = NULL; - - bcm43xx_destroy_dmaring(dma->tx_ring5); - dma->tx_ring5 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring4); - dma->tx_ring4 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring3); - dma->tx_ring3 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring2); - dma->tx_ring2 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring1); - dma->tx_ring1 = NULL; - bcm43xx_destroy_dmaring(dma->tx_ring0); - dma->tx_ring0 = NULL; -} - -int bcm43xx_dma_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); - struct bcm43xx_dmaring *ring; - int err = -ENOMEM; - int dma64 = 0; - - bcm->dma_mask = bcm43xx_get_supported_dma_mask(bcm); - if (bcm->dma_mask == DMA_64BIT_MASK) - dma64 = 1; - err = pci_set_dma_mask(bcm->pci_dev, bcm->dma_mask); - if (err) - goto no_dma; - err = pci_set_consistent_dma_mask(bcm->pci_dev, bcm->dma_mask); - if (err) - goto no_dma; - - /* setup TX DMA channels. */ - ring = bcm43xx_setup_dmaring(bcm, 0, 1, dma64); - if (!ring) - goto out; - dma->tx_ring0 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 1, 1, dma64); - if (!ring) - goto err_destroy_tx0; - dma->tx_ring1 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 2, 1, dma64); - if (!ring) - goto err_destroy_tx1; - dma->tx_ring2 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 3, 1, dma64); - if (!ring) - goto err_destroy_tx2; - dma->tx_ring3 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 4, 1, dma64); - if (!ring) - goto err_destroy_tx3; - dma->tx_ring4 = ring; - - ring = bcm43xx_setup_dmaring(bcm, 5, 1, dma64); - if (!ring) - goto err_destroy_tx4; - dma->tx_ring5 = ring; - - /* setup RX DMA channels. */ - ring = bcm43xx_setup_dmaring(bcm, 0, 0, dma64); - if (!ring) - goto err_destroy_tx5; - dma->rx_ring0 = ring; - - if (bcm->current_core->rev < 5) { - ring = bcm43xx_setup_dmaring(bcm, 3, 0, dma64); - if (!ring) - goto err_destroy_rx0; - dma->rx_ring3 = ring; - } - - dprintk(KERN_INFO PFX "%d-bit DMA initialized\n", - (bcm->dma_mask == DMA_64BIT_MASK) ? 64 : - (bcm->dma_mask == DMA_32BIT_MASK) ? 32 : 30); - err = 0; -out: - return err; - -err_destroy_rx0: - bcm43xx_destroy_dmaring(dma->rx_ring0); - dma->rx_ring0 = NULL; -err_destroy_tx5: - bcm43xx_destroy_dmaring(dma->tx_ring5); - dma->tx_ring5 = NULL; -err_destroy_tx4: - bcm43xx_destroy_dmaring(dma->tx_ring4); - dma->tx_ring4 = NULL; -err_destroy_tx3: - bcm43xx_destroy_dmaring(dma->tx_ring3); - dma->tx_ring3 = NULL; -err_destroy_tx2: - bcm43xx_destroy_dmaring(dma->tx_ring2); - dma->tx_ring2 = NULL; -err_destroy_tx1: - bcm43xx_destroy_dmaring(dma->tx_ring1); - dma->tx_ring1 = NULL; -err_destroy_tx0: - bcm43xx_destroy_dmaring(dma->tx_ring0); - dma->tx_ring0 = NULL; -no_dma: -#ifdef CONFIG_BCM43XX_PIO - printk(KERN_WARNING PFX "DMA not supported on this device." - " Falling back to PIO.\n"); - bcm->__using_pio = 1; - return -ENOSYS; -#else - printk(KERN_ERR PFX "FATAL: DMA not supported and PIO not configured. " - "Please recompile the driver with PIO support.\n"); - return -ENODEV; -#endif /* CONFIG_BCM43XX_PIO */ -} - -/* Generate a cookie for the TX header. */ -static u16 generate_cookie(struct bcm43xx_dmaring *ring, - int slot) -{ - u16 cookie = 0x1000; - - /* Use the upper 4 bits of the cookie as - * DMA controller ID and store the slot number - * in the lower 12 bits. - * Note that the cookie must never be 0, as this - * is a special value used in RX path. - */ - switch (ring->index) { - case 0: - cookie = 0xA000; - break; - case 1: - cookie = 0xB000; - break; - case 2: - cookie = 0xC000; - break; - case 3: - cookie = 0xD000; - break; - case 4: - cookie = 0xE000; - break; - case 5: - cookie = 0xF000; - break; - } - assert(((u16)slot & 0xF000) == 0x0000); - cookie |= (u16)slot; - - return cookie; -} - -/* Inspect a cookie and find out to which controller/slot it belongs. */ -static -struct bcm43xx_dmaring * parse_cookie(struct bcm43xx_private *bcm, - u16 cookie, int *slot) -{ - struct bcm43xx_dma *dma = bcm43xx_current_dma(bcm); - struct bcm43xx_dmaring *ring = NULL; - - switch (cookie & 0xF000) { - case 0xA000: - ring = dma->tx_ring0; - break; - case 0xB000: - ring = dma->tx_ring1; - break; - case 0xC000: - ring = dma->tx_ring2; - break; - case 0xD000: - ring = dma->tx_ring3; - break; - case 0xE000: - ring = dma->tx_ring4; - break; - case 0xF000: - ring = dma->tx_ring5; - break; - default: - assert(0); - } - *slot = (cookie & 0x0FFF); - assert(*slot >= 0 && *slot < ring->nr_slots); - - return ring; -} - -static void dmacontroller_poke_tx(struct bcm43xx_dmaring *ring, - int slot) -{ - u16 offset; - int descsize; - - /* Everything is ready to start. Buffers are DMA mapped and - * associated with slots. - * "slot" is the last slot of the new frame we want to transmit. - * Close your seat belts now, please. - */ - wmb(); - slot = next_slot(ring, slot); - offset = (ring->dma64) ? BCM43xx_DMA64_TXINDEX : BCM43xx_DMA32_TXINDEX; - descsize = (ring->dma64) ? sizeof(struct bcm43xx_dmadesc64) - : sizeof(struct bcm43xx_dmadesc32); - bcm43xx_dma_write(ring, offset, - (u32)(slot * descsize)); -} - -static void dma_tx_fragment(struct bcm43xx_dmaring *ring, - struct sk_buff *skb, - u8 cur_frag) -{ - int slot; - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - dma_addr_t dmaaddr; - struct sk_buff *bounce_skb; - - assert(skb_shinfo(skb)->nr_frags == 0); - - slot = request_slot(ring); - desc = bcm43xx_dma_idx2desc(ring, slot, &meta); - - /* Add a device specific TX header. */ - assert(skb_headroom(skb) >= sizeof(struct bcm43xx_txhdr)); - /* Reserve enough headroom for the device tx header. */ - __skb_push(skb, sizeof(struct bcm43xx_txhdr)); - /* Now calculate and add the tx header. - * The tx header includes the PLCP header. - */ - bcm43xx_generate_txhdr(ring->bcm, - (struct bcm43xx_txhdr *)skb->data, - skb->data + sizeof(struct bcm43xx_txhdr), - skb->len - sizeof(struct bcm43xx_txhdr), - (cur_frag == 0), - generate_cookie(ring, slot)); - dmaaddr = map_descbuffer(ring, skb->data, skb->len, 1); - if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) { - /* chip cannot handle DMA to/from > 1GB, use bounce buffer (copied from b44 driver) */ - if (!dma_mapping_error(dmaaddr)) - unmap_descbuffer(ring, dmaaddr, skb->len, 1); - bounce_skb = __dev_alloc_skb(skb->len, GFP_ATOMIC|GFP_DMA); - if (!bounce_skb) - return; - dmaaddr = map_descbuffer(ring, bounce_skb->data, bounce_skb->len, 1); - if (dma_mapping_error(dmaaddr) || dmaaddr + skb->len > ring->bcm->dma_mask) { - if (!dma_mapping_error(dmaaddr)) - unmap_descbuffer(ring, dmaaddr, skb->len, 1); - dev_kfree_skb_any(bounce_skb); - assert(0); - return; - } - skb_copy_from_linear_data(skb, skb_put(bounce_skb, skb->len), - skb->len); - dev_kfree_skb_any(skb); - skb = bounce_skb; - } - - meta->skb = skb; - meta->dmaaddr = dmaaddr; - - fill_descriptor(ring, desc, dmaaddr, - skb->len, 1, 1, 1); - - /* Now transfer the whole frame. */ - dmacontroller_poke_tx(ring, slot); -} - -int bcm43xx_dma_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - /* We just received a packet from the kernel network subsystem. - * Add headers and DMA map the memory. Poke - * the device to send the stuff. - * Note that this is called from atomic context. - */ - struct bcm43xx_dmaring *ring = bcm43xx_current_dma(bcm)->tx_ring1; - u8 i; - struct sk_buff *skb; - - assert(ring->tx); - if (unlikely(free_slots(ring) < txb->nr_frags)) { - /* The queue should be stopped, - * if we are low on free slots. - * If this ever triggers, we have to lower the suspend_mark. - */ - dprintkl(KERN_ERR PFX "Out of DMA descriptor slots!\n"); - return -ENOMEM; - } - - for (i = 0; i < txb->nr_frags; i++) { - skb = txb->fragments[i]; - /* Take skb from ieee80211_txb_free */ - txb->fragments[i] = NULL; - dma_tx_fragment(ring, skb, i); - } - ieee80211_txb_free(txb); - - return 0; -} - -void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ - struct bcm43xx_dmaring *ring; - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - int is_last_fragment; - int slot; - u32 tmp; - - ring = parse_cookie(bcm, status->cookie, &slot); - assert(ring); - assert(ring->tx); - while (1) { - assert(slot >= 0 && slot < ring->nr_slots); - desc = bcm43xx_dma_idx2desc(ring, slot, &meta); - - if (ring->dma64) { - tmp = le32_to_cpu(desc->dma64.control0); - is_last_fragment = !!(tmp & BCM43xx_DMA64_DCTL0_FRAMEEND); - } else { - tmp = le32_to_cpu(desc->dma32.control); - is_last_fragment = !!(tmp & BCM43xx_DMA32_DCTL_FRAMEEND); - } - unmap_descbuffer(ring, meta->dmaaddr, meta->skb->len, 1); - free_descriptor_buffer(ring, meta, 1); - /* Everything belonging to the slot is unmapped - * and freed, so we can return it. - */ - return_slot(ring, slot); - - if (is_last_fragment) - break; - slot = next_slot(ring, slot); - } - bcm->stats.last_tx = jiffies; -} - -static void dma_rx(struct bcm43xx_dmaring *ring, - int *slot) -{ - struct bcm43xx_dmadesc_generic *desc; - struct bcm43xx_dmadesc_meta *meta; - struct bcm43xx_rxhdr *rxhdr; - struct sk_buff *skb; - u16 len; - int err; - dma_addr_t dmaaddr; - - desc = bcm43xx_dma_idx2desc(ring, *slot, &meta); - - sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); - skb = meta->skb; - - if (ring->index == 3) { - /* We received an xmit status. */ - struct bcm43xx_hwxmitstatus *hw = (struct bcm43xx_hwxmitstatus *)skb->data; - struct bcm43xx_xmitstatus stat; - int i = 0; - - stat.cookie = le16_to_cpu(hw->cookie); - while (stat.cookie == 0) { - if (unlikely(++i >= 10000)) { - assert(0); - break; - } - udelay(2); - barrier(); - stat.cookie = le16_to_cpu(hw->cookie); - } - stat.flags = hw->flags; - stat.cnt1 = hw->cnt1; - stat.cnt2 = hw->cnt2; - stat.seq = le16_to_cpu(hw->seq); - stat.unknown = le16_to_cpu(hw->unknown); - - bcm43xx_debugfs_log_txstat(ring->bcm, &stat); - bcm43xx_dma_handle_xmitstatus(ring->bcm, &stat); - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, ring->rx_buffersize); - - return; - } - rxhdr = (struct bcm43xx_rxhdr *)skb->data; - len = le16_to_cpu(rxhdr->frame_length); - if (len == 0) { - int i = 0; - - do { - udelay(2); - barrier(); - len = le16_to_cpu(rxhdr->frame_length); - } while (len == 0 && i++ < 5); - if (unlikely(len == 0)) { - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - goto drop; - } - } - if (unlikely(len > ring->rx_buffersize)) { - /* The data did not fit into one descriptor buffer - * and is split over multiple buffers. - * This should never happen, as we try to allocate buffers - * big enough. So simply ignore this packet. - */ - int cnt = 0; - s32 tmp = len; - - while (1) { - desc = bcm43xx_dma_idx2desc(ring, *slot, &meta); - /* recycle the descriptor buffer. */ - sync_descbuffer_for_device(ring, meta->dmaaddr, - ring->rx_buffersize); - *slot = next_slot(ring, *slot); - cnt++; - tmp -= ring->rx_buffersize; - if (tmp <= 0) - break; - } - printkl(KERN_ERR PFX "DMA RX buffer too small " - "(len: %u, buffer: %u, nr-dropped: %d)\n", - len, ring->rx_buffersize, cnt); - goto drop; - } - len -= IEEE80211_FCS_LEN; - - dmaaddr = meta->dmaaddr; - err = setup_rx_descbuffer(ring, desc, meta, GFP_ATOMIC); - if (unlikely(err)) { - dprintkl(KERN_ERR PFX "DMA RX: setup_rx_descbuffer() failed\n"); - sync_descbuffer_for_device(ring, dmaaddr, - ring->rx_buffersize); - goto drop; - } - - unmap_descbuffer(ring, dmaaddr, ring->rx_buffersize, 0); - skb_put(skb, len + ring->frameoffset); - skb_pull(skb, ring->frameoffset); - - err = bcm43xx_rx(ring->bcm, skb, rxhdr); - if (err) { - dev_kfree_skb_irq(skb); - goto drop; - } - -drop: - return; -} - -void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) -{ - u32 status; - u16 descptr; - int slot, current_slot; -#ifdef CONFIG_BCM43XX_DEBUG - int used_slots = 0; -#endif - - assert(!ring->tx); - if (ring->dma64) { - status = bcm43xx_dma_read(ring, BCM43xx_DMA64_RXSTATUS); - descptr = (status & BCM43xx_DMA64_RXSTATDPTR); - current_slot = descptr / sizeof(struct bcm43xx_dmadesc64); - } else { - status = bcm43xx_dma_read(ring, BCM43xx_DMA32_RXSTATUS); - descptr = (status & BCM43xx_DMA32_RXDPTR); - current_slot = descptr / sizeof(struct bcm43xx_dmadesc32); - } - assert(current_slot >= 0 && current_slot < ring->nr_slots); - - slot = ring->current_slot; - for ( ; slot != current_slot; slot = next_slot(ring, slot)) { - dma_rx(ring, &slot); -#ifdef CONFIG_BCM43XX_DEBUG - if (++used_slots > ring->max_used_slots) - ring->max_used_slots = used_slots; -#endif - } - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_RXINDEX, - (u32)(slot * sizeof(struct bcm43xx_dmadesc64))); - } else { - bcm43xx_dma_write(ring, BCM43xx_DMA32_RXINDEX, - (u32)(slot * sizeof(struct bcm43xx_dmadesc32))); - } - ring->current_slot = slot; -} - -void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) -{ - assert(ring->tx); - bcm43xx_power_saving_ctl_bits(ring->bcm, -1, 1); - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, - bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL) - | BCM43xx_DMA64_TXSUSPEND); - } else { - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, - bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL) - | BCM43xx_DMA32_TXSUSPEND); - } -} - -void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) -{ - assert(ring->tx); - if (ring->dma64) { - bcm43xx_dma_write(ring, BCM43xx_DMA64_TXCTL, - bcm43xx_dma_read(ring, BCM43xx_DMA64_TXCTL) - & ~BCM43xx_DMA64_TXSUSPEND); - } else { - bcm43xx_dma_write(ring, BCM43xx_DMA32_TXCTL, - bcm43xx_dma_read(ring, BCM43xx_DMA32_TXCTL) - & ~BCM43xx_DMA32_TXSUSPEND); - } - bcm43xx_power_saving_ctl_bits(ring->bcm, -1, -1); -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h b/drivers/net/wireless/bcm43xx/bcm43xx_dma.h deleted file mode 100644 index d1105e569a41..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_dma.h +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef BCM43xx_DMA_H_ -#define BCM43xx_DMA_H_ - -#include -#include -#include -#include -#include -#include - - -/* DMA-Interrupt reasons. */ -#define BCM43xx_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \ - | (1 << 14) | (1 << 15)) -#define BCM43xx_DMAIRQ_NONFATALMASK (1 << 13) -#define BCM43xx_DMAIRQ_RX_DONE (1 << 16) - - -/*** 32-bit DMA Engine. ***/ - -/* 32-bit DMA controller registers. */ -#define BCM43xx_DMA32_TXCTL 0x00 -#define BCM43xx_DMA32_TXENABLE 0x00000001 -#define BCM43xx_DMA32_TXSUSPEND 0x00000002 -#define BCM43xx_DMA32_TXLOOPBACK 0x00000004 -#define BCM43xx_DMA32_TXFLUSH 0x00000010 -#define BCM43xx_DMA32_TXADDREXT_MASK 0x00030000 -#define BCM43xx_DMA32_TXADDREXT_SHIFT 16 -#define BCM43xx_DMA32_TXRING 0x04 -#define BCM43xx_DMA32_TXINDEX 0x08 -#define BCM43xx_DMA32_TXSTATUS 0x0C -#define BCM43xx_DMA32_TXDPTR 0x00000FFF -#define BCM43xx_DMA32_TXSTATE 0x0000F000 -#define BCM43xx_DMA32_TXSTAT_DISABLED 0x00000000 -#define BCM43xx_DMA32_TXSTAT_ACTIVE 0x00001000 -#define BCM43xx_DMA32_TXSTAT_IDLEWAIT 0x00002000 -#define BCM43xx_DMA32_TXSTAT_STOPPED 0x00003000 -#define BCM43xx_DMA32_TXSTAT_SUSP 0x00004000 -#define BCM43xx_DMA32_TXERROR 0x000F0000 -#define BCM43xx_DMA32_TXERR_NOERR 0x00000000 -#define BCM43xx_DMA32_TXERR_PROT 0x00010000 -#define BCM43xx_DMA32_TXERR_UNDERRUN 0x00020000 -#define BCM43xx_DMA32_TXERR_BUFREAD 0x00030000 -#define BCM43xx_DMA32_TXERR_DESCREAD 0x00040000 -#define BCM43xx_DMA32_TXACTIVE 0xFFF00000 -#define BCM43xx_DMA32_RXCTL 0x10 -#define BCM43xx_DMA32_RXENABLE 0x00000001 -#define BCM43xx_DMA32_RXFROFF_MASK 0x000000FE -#define BCM43xx_DMA32_RXFROFF_SHIFT 1 -#define BCM43xx_DMA32_RXDIRECTFIFO 0x00000100 -#define BCM43xx_DMA32_RXADDREXT_MASK 0x00030000 -#define BCM43xx_DMA32_RXADDREXT_SHIFT 16 -#define BCM43xx_DMA32_RXRING 0x14 -#define BCM43xx_DMA32_RXINDEX 0x18 -#define BCM43xx_DMA32_RXSTATUS 0x1C -#define BCM43xx_DMA32_RXDPTR 0x00000FFF -#define BCM43xx_DMA32_RXSTATE 0x0000F000 -#define BCM43xx_DMA32_RXSTAT_DISABLED 0x00000000 -#define BCM43xx_DMA32_RXSTAT_ACTIVE 0x00001000 -#define BCM43xx_DMA32_RXSTAT_IDLEWAIT 0x00002000 -#define BCM43xx_DMA32_RXSTAT_STOPPED 0x00003000 -#define BCM43xx_DMA32_RXERROR 0x000F0000 -#define BCM43xx_DMA32_RXERR_NOERR 0x00000000 -#define BCM43xx_DMA32_RXERR_PROT 0x00010000 -#define BCM43xx_DMA32_RXERR_OVERFLOW 0x00020000 -#define BCM43xx_DMA32_RXERR_BUFWRITE 0x00030000 -#define BCM43xx_DMA32_RXERR_DESCREAD 0x00040000 -#define BCM43xx_DMA32_RXACTIVE 0xFFF00000 - -/* 32-bit DMA descriptor. */ -struct bcm43xx_dmadesc32 { - __le32 control; - __le32 address; -} __attribute__((__packed__)); -#define BCM43xx_DMA32_DCTL_BYTECNT 0x00001FFF -#define BCM43xx_DMA32_DCTL_ADDREXT_MASK 0x00030000 -#define BCM43xx_DMA32_DCTL_ADDREXT_SHIFT 16 -#define BCM43xx_DMA32_DCTL_DTABLEEND 0x10000000 -#define BCM43xx_DMA32_DCTL_IRQ 0x20000000 -#define BCM43xx_DMA32_DCTL_FRAMEEND 0x40000000 -#define BCM43xx_DMA32_DCTL_FRAMESTART 0x80000000 - -/* Address field Routing value. */ -#define BCM43xx_DMA32_ROUTING 0xC0000000 -#define BCM43xx_DMA32_ROUTING_SHIFT 30 -#define BCM43xx_DMA32_NOTRANS 0x00000000 -#define BCM43xx_DMA32_CLIENTTRANS 0x40000000 - - - -/*** 64-bit DMA Engine. ***/ - -/* 64-bit DMA controller registers. */ -#define BCM43xx_DMA64_TXCTL 0x00 -#define BCM43xx_DMA64_TXENABLE 0x00000001 -#define BCM43xx_DMA64_TXSUSPEND 0x00000002 -#define BCM43xx_DMA64_TXLOOPBACK 0x00000004 -#define BCM43xx_DMA64_TXFLUSH 0x00000010 -#define BCM43xx_DMA64_TXADDREXT_MASK 0x00030000 -#define BCM43xx_DMA64_TXADDREXT_SHIFT 16 -#define BCM43xx_DMA64_TXINDEX 0x04 -#define BCM43xx_DMA64_TXRINGLO 0x08 -#define BCM43xx_DMA64_TXRINGHI 0x0C -#define BCM43xx_DMA64_TXSTATUS 0x10 -#define BCM43xx_DMA64_TXSTATDPTR 0x00001FFF -#define BCM43xx_DMA64_TXSTAT 0xF0000000 -#define BCM43xx_DMA64_TXSTAT_DISABLED 0x00000000 -#define BCM43xx_DMA64_TXSTAT_ACTIVE 0x10000000 -#define BCM43xx_DMA64_TXSTAT_IDLEWAIT 0x20000000 -#define BCM43xx_DMA64_TXSTAT_STOPPED 0x30000000 -#define BCM43xx_DMA64_TXSTAT_SUSP 0x40000000 -#define BCM43xx_DMA64_TXERROR 0x14 -#define BCM43xx_DMA64_TXERRDPTR 0x0001FFFF -#define BCM43xx_DMA64_TXERR 0xF0000000 -#define BCM43xx_DMA64_TXERR_NOERR 0x00000000 -#define BCM43xx_DMA64_TXERR_PROT 0x10000000 -#define BCM43xx_DMA64_TXERR_UNDERRUN 0x20000000 -#define BCM43xx_DMA64_TXERR_TRANSFER 0x30000000 -#define BCM43xx_DMA64_TXERR_DESCREAD 0x40000000 -#define BCM43xx_DMA64_TXERR_CORE 0x50000000 -#define BCM43xx_DMA64_RXCTL 0x20 -#define BCM43xx_DMA64_RXENABLE 0x00000001 -#define BCM43xx_DMA64_RXFROFF_MASK 0x000000FE -#define BCM43xx_DMA64_RXFROFF_SHIFT 1 -#define BCM43xx_DMA64_RXDIRECTFIFO 0x00000100 -#define BCM43xx_DMA64_RXADDREXT_MASK 0x00030000 -#define BCM43xx_DMA64_RXADDREXT_SHIFT 16 -#define BCM43xx_DMA64_RXINDEX 0x24 -#define BCM43xx_DMA64_RXRINGLO 0x28 -#define BCM43xx_DMA64_RXRINGHI 0x2C -#define BCM43xx_DMA64_RXSTATUS 0x30 -#define BCM43xx_DMA64_RXSTATDPTR 0x00001FFF -#define BCM43xx_DMA64_RXSTAT 0xF0000000 -#define BCM43xx_DMA64_RXSTAT_DISABLED 0x00000000 -#define BCM43xx_DMA64_RXSTAT_ACTIVE 0x10000000 -#define BCM43xx_DMA64_RXSTAT_IDLEWAIT 0x20000000 -#define BCM43xx_DMA64_RXSTAT_STOPPED 0x30000000 -#define BCM43xx_DMA64_RXSTAT_SUSP 0x40000000 -#define BCM43xx_DMA64_RXERROR 0x34 -#define BCM43xx_DMA64_RXERRDPTR 0x0001FFFF -#define BCM43xx_DMA64_RXERR 0xF0000000 -#define BCM43xx_DMA64_RXERR_NOERR 0x00000000 -#define BCM43xx_DMA64_RXERR_PROT 0x10000000 -#define BCM43xx_DMA64_RXERR_UNDERRUN 0x20000000 -#define BCM43xx_DMA64_RXERR_TRANSFER 0x30000000 -#define BCM43xx_DMA64_RXERR_DESCREAD 0x40000000 -#define BCM43xx_DMA64_RXERR_CORE 0x50000000 - -/* 64-bit DMA descriptor. */ -struct bcm43xx_dmadesc64 { - __le32 control0; - __le32 control1; - __le32 address_low; - __le32 address_high; -} __attribute__((__packed__)); -#define BCM43xx_DMA64_DCTL0_DTABLEEND 0x10000000 -#define BCM43xx_DMA64_DCTL0_IRQ 0x20000000 -#define BCM43xx_DMA64_DCTL0_FRAMEEND 0x40000000 -#define BCM43xx_DMA64_DCTL0_FRAMESTART 0x80000000 -#define BCM43xx_DMA64_DCTL1_BYTECNT 0x00001FFF -#define BCM43xx_DMA64_DCTL1_ADDREXT_MASK 0x00030000 -#define BCM43xx_DMA64_DCTL1_ADDREXT_SHIFT 16 - -/* Address field Routing value. */ -#define BCM43xx_DMA64_ROUTING 0xC0000000 -#define BCM43xx_DMA64_ROUTING_SHIFT 30 -#define BCM43xx_DMA64_NOTRANS 0x00000000 -#define BCM43xx_DMA64_CLIENTTRANS 0x80000000 - - - -struct bcm43xx_dmadesc_generic { - union { - struct bcm43xx_dmadesc32 dma32; - struct bcm43xx_dmadesc64 dma64; - } __attribute__((__packed__)); -} __attribute__((__packed__)); - - -/* Misc DMA constants */ -#define BCM43xx_DMA_RINGMEMSIZE PAGE_SIZE -#define BCM43xx_DMA0_RX_FRAMEOFFSET 30 -#define BCM43xx_DMA3_RX_FRAMEOFFSET 0 - - -/* DMA engine tuning knobs */ -#define BCM43xx_TXRING_SLOTS 512 -#define BCM43xx_RXRING_SLOTS 64 -#define BCM43xx_DMA0_RX_BUFFERSIZE (2304 + 100) -#define BCM43xx_DMA3_RX_BUFFERSIZE 16 -/* Suspend the tx queue, if less than this percent slots are free. */ -#define BCM43xx_TXSUSPEND_PERCENT 20 -/* Resume the tx queue, if more than this percent slots are free. */ -#define BCM43xx_TXRESUME_PERCENT 50 - - - -#ifdef CONFIG_BCM43XX_DMA - - -struct sk_buff; -struct bcm43xx_private; -struct bcm43xx_xmitstatus; - - -struct bcm43xx_dmadesc_meta { - /* The kernel DMA-able buffer. */ - struct sk_buff *skb; - /* DMA base bus-address of the descriptor buffer. */ - dma_addr_t dmaaddr; -}; - -struct bcm43xx_dmaring { - /* Kernel virtual base address of the ring memory. */ - void *descbase; - /* Meta data about all descriptors. */ - struct bcm43xx_dmadesc_meta *meta; - /* DMA Routing value. */ - u32 routing; - /* (Unadjusted) DMA base bus-address of the ring memory. */ - dma_addr_t dmabase; - /* Number of descriptor slots in the ring. */ - int nr_slots; - /* Number of used descriptor slots. */ - int used_slots; - /* Currently used slot in the ring. */ - int current_slot; - /* Marks to suspend/resume the queue. */ - int suspend_mark; - int resume_mark; - /* Frameoffset in octets. */ - u32 frameoffset; - /* Descriptor buffer size. */ - u16 rx_buffersize; - /* The MMIO base register of the DMA controller. */ - u16 mmio_base; - /* DMA controller index number (0-5). */ - int index; - /* Boolean. Is this a TX ring? */ - u8 tx; - /* Boolean. 64bit DMA if true, 32bit DMA otherwise. */ - u8 dma64; - /* Boolean. Are transfers suspended on this ring? */ - u8 suspended; - struct bcm43xx_private *bcm; -#ifdef CONFIG_BCM43XX_DEBUG - /* Maximum number of used slots. */ - int max_used_slots; -#endif /* CONFIG_BCM43XX_DEBUG*/ -}; - - -static inline -int bcm43xx_dma_desc2idx(struct bcm43xx_dmaring *ring, - struct bcm43xx_dmadesc_generic *desc) -{ - if (ring->dma64) { - struct bcm43xx_dmadesc64 *dd64 = ring->descbase; - return (int)(&(desc->dma64) - dd64); - } else { - struct bcm43xx_dmadesc32 *dd32 = ring->descbase; - return (int)(&(desc->dma32) - dd32); - } -} - -static inline -struct bcm43xx_dmadesc_generic * bcm43xx_dma_idx2desc(struct bcm43xx_dmaring *ring, - int slot, - struct bcm43xx_dmadesc_meta **meta) -{ - *meta = &(ring->meta[slot]); - if (ring->dma64) { - struct bcm43xx_dmadesc64 *dd64 = ring->descbase; - return (struct bcm43xx_dmadesc_generic *)(&(dd64[slot])); - } else { - struct bcm43xx_dmadesc32 *dd32 = ring->descbase; - return (struct bcm43xx_dmadesc_generic *)(&(dd32[slot])); - } -} - -static inline -u32 bcm43xx_dma_read(struct bcm43xx_dmaring *ring, - u16 offset) -{ - return bcm43xx_read32(ring->bcm, ring->mmio_base + offset); -} - -static inline -void bcm43xx_dma_write(struct bcm43xx_dmaring *ring, - u16 offset, u32 value) -{ - bcm43xx_write32(ring->bcm, ring->mmio_base + offset, value); -} - - -int bcm43xx_dma_init(struct bcm43xx_private *bcm); -void bcm43xx_dma_free(struct bcm43xx_private *bcm); - -int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, - u16 dmacontroller_mmio_base, - int dma64); -int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, - u16 dmacontroller_mmio_base, - int dma64); - -u16 bcm43xx_dmacontroller_base(int dma64bit, int dmacontroller_idx); - -void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring); -void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring); - -void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status); - -int bcm43xx_dma_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb); -void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring); - -/* Helper function that returns the dma mask for this device. */ -static inline -u64 bcm43xx_get_supported_dma_mask(struct bcm43xx_private *bcm) -{ - int dma64 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH) & - BCM43xx_SBTMSTATEHIGH_DMA64BIT; - u16 mmio_base = bcm43xx_dmacontroller_base(dma64, 0); - u32 mask = BCM43xx_DMA32_TXADDREXT_MASK; - - if (dma64) - return DMA_64BIT_MASK; - bcm43xx_write32(bcm, mmio_base + BCM43xx_DMA32_TXCTL, mask); - if (bcm43xx_read32(bcm, mmio_base + BCM43xx_DMA32_TXCTL) & mask) - return DMA_32BIT_MASK; - return DMA_30BIT_MASK; -} - -#else /* CONFIG_BCM43XX_DMA */ - - -static inline -int bcm43xx_dma_init(struct bcm43xx_private *bcm) -{ - return 0; -} -static inline -void bcm43xx_dma_free(struct bcm43xx_private *bcm) -{ -} -static inline -int bcm43xx_dmacontroller_rx_reset(struct bcm43xx_private *bcm, - u16 dmacontroller_mmio_base, - int dma64) -{ - return 0; -} -static inline -int bcm43xx_dmacontroller_tx_reset(struct bcm43xx_private *bcm, - u16 dmacontroller_mmio_base, - int dma64) -{ - return 0; -} -static inline -int bcm43xx_dma_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - return 0; -} -static inline -void bcm43xx_dma_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ -} -static inline -void bcm43xx_dma_rx(struct bcm43xx_dmaring *ring) -{ -} -static inline -void bcm43xx_dma_tx_suspend(struct bcm43xx_dmaring *ring) -{ -} -static inline -void bcm43xx_dma_tx_resume(struct bcm43xx_dmaring *ring) -{ -} - -#endif /* CONFIG_BCM43XX_DMA */ -#endif /* BCM43xx_DMA_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c deleted file mode 100644 index d2df6a0100a1..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.c +++ /dev/null @@ -1,50 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - ethtool support - - Copyright (c) 2006 Jason Lunz - - Some code in this file is derived from the 8139too.c driver - Copyright (C) 2002 Jeff Garzik - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx.h" -#include "bcm43xx_ethtool.h" - -#include -#include -#include -#include - - -static void bcm43xx_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(dev); - - strncpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - strncpy(info->version, utsname()->release, sizeof(info->version)); - strncpy(info->bus_info, pci_name(bcm->pci_dev), ETHTOOL_BUSINFO_LEN); -} - -const struct ethtool_ops bcm43xx_ethtool_ops = { - .get_drvinfo = bcm43xx_get_drvinfo, - .get_link = ethtool_op_get_link, -}; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h b/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h deleted file mode 100644 index 6f8d42d3cdf5..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ethtool.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef BCM43xx_ETHTOOL_H_ -#define BCM43xx_ETHTOOL_H_ - -#include - -extern const struct ethtool_ops bcm43xx_ethtool_ops; - -#endif /* BCM43xx_ETHTOOL_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c deleted file mode 100644 index f2b8dbac55a4..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.c +++ /dev/null @@ -1,352 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx.h" -#include "bcm43xx_ilt.h" -#include "bcm43xx_phy.h" - - -/**** Initial Internal Lookup Tables ****/ - -const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE] = { - 0xFEB93FFD, 0xFEC63FFD, /* 0 */ - 0xFED23FFD, 0xFEDF3FFD, - 0xFEEC3FFE, 0xFEF83FFE, - 0xFF053FFE, 0xFF113FFE, - 0xFF1E3FFE, 0xFF2A3FFF, /* 8 */ - 0xFF373FFF, 0xFF443FFF, - 0xFF503FFF, 0xFF5D3FFF, - 0xFF693FFF, 0xFF763FFF, - 0xFF824000, 0xFF8F4000, /* 16 */ - 0xFF9B4000, 0xFFA84000, - 0xFFB54000, 0xFFC14000, - 0xFFCE4000, 0xFFDA4000, - 0xFFE74000, 0xFFF34000, /* 24 */ - 0x00004000, 0x000D4000, - 0x00194000, 0x00264000, - 0x00324000, 0x003F4000, - 0x004B4000, 0x00584000, /* 32 */ - 0x00654000, 0x00714000, - 0x007E4000, 0x008A3FFF, - 0x00973FFF, 0x00A33FFF, - 0x00B03FFF, 0x00BC3FFF, /* 40 */ - 0x00C93FFF, 0x00D63FFF, - 0x00E23FFE, 0x00EF3FFE, - 0x00FB3FFE, 0x01083FFE, - 0x01143FFE, 0x01213FFD, /* 48 */ - 0x012E3FFD, 0x013A3FFD, - 0x01473FFD, -}; - -const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE] = { - 0xDB93CB87, 0xD666CF64, /* 0 */ - 0xD1FDD358, 0xCDA6D826, - 0xCA38DD9F, 0xC729E2B4, - 0xC469E88E, 0xC26AEE2B, - 0xC0DEF46C, 0xC073FA62, /* 8 */ - 0xC01D00D5, 0xC0760743, - 0xC1560D1E, 0xC2E51369, - 0xC4ED18FF, 0xC7AC1ED7, - 0xCB2823B2, 0xCEFA28D9, /* 16 */ - 0xD2F62D3F, 0xD7BB3197, - 0xDCE53568, 0xE1FE3875, - 0xE7D13B35, 0xED663D35, - 0xF39B3EC4, 0xF98E3FA7, /* 24 */ - 0x00004000, 0x06723FA7, - 0x0C653EC4, 0x129A3D35, - 0x182F3B35, 0x1E023875, - 0x231B3568, 0x28453197, /* 32 */ - 0x2D0A2D3F, 0x310628D9, - 0x34D823B2, 0x38541ED7, - 0x3B1318FF, 0x3D1B1369, - 0x3EAA0D1E, 0x3F8A0743, /* 40 */ - 0x3FE300D5, 0x3F8DFA62, - 0x3F22F46C, 0x3D96EE2B, - 0x3B97E88E, 0x38D7E2B4, - 0x35C8DD9F, 0x325AD826, /* 48 */ - 0x2E03D358, 0x299ACF64, - 0x246DCB87, -}; - -const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE] = { - 0x0082, 0x0082, 0x0102, 0x0182, /* 0 */ - 0x0202, 0x0282, 0x0302, 0x0382, - 0x0402, 0x0482, 0x0502, 0x0582, - 0x05E2, 0x0662, 0x06E2, 0x0762, - 0x07E2, 0x0842, 0x08C2, 0x0942, /* 16 */ - 0x09C2, 0x0A22, 0x0AA2, 0x0B02, - 0x0B82, 0x0BE2, 0x0C62, 0x0CC2, - 0x0D42, 0x0DA2, 0x0E02, 0x0E62, - 0x0EE2, 0x0F42, 0x0FA2, 0x1002, /* 32 */ - 0x1062, 0x10C2, 0x1122, 0x1182, - 0x11E2, 0x1242, 0x12A2, 0x12E2, - 0x1342, 0x13A2, 0x1402, 0x1442, - 0x14A2, 0x14E2, 0x1542, 0x1582, /* 48 */ - 0x15E2, 0x1622, 0x1662, 0x16C1, - 0x1701, 0x1741, 0x1781, 0x17E1, - 0x1821, 0x1861, 0x18A1, 0x18E1, - 0x1921, 0x1961, 0x19A1, 0x19E1, /* 64 */ - 0x1A21, 0x1A61, 0x1AA1, 0x1AC1, - 0x1B01, 0x1B41, 0x1B81, 0x1BA1, - 0x1BE1, 0x1C21, 0x1C41, 0x1C81, - 0x1CA1, 0x1CE1, 0x1D01, 0x1D41, /* 80 */ - 0x1D61, 0x1DA1, 0x1DC1, 0x1E01, - 0x1E21, 0x1E61, 0x1E81, 0x1EA1, - 0x1EE1, 0x1F01, 0x1F21, 0x1F41, - 0x1F81, 0x1FA1, 0x1FC1, 0x1FE1, /* 96 */ - 0x2001, 0x2041, 0x2061, 0x2081, - 0x20A1, 0x20C1, 0x20E1, 0x2101, - 0x2121, 0x2141, 0x2161, 0x2181, - 0x21A1, 0x21C1, 0x21E1, 0x2201, /* 112 */ - 0x2221, 0x2241, 0x2261, 0x2281, - 0x22A1, 0x22C1, 0x22C1, 0x22E1, - 0x2301, 0x2321, 0x2341, 0x2361, - 0x2361, 0x2381, 0x23A1, 0x23C1, /* 128 */ - 0x23E1, 0x23E1, 0x2401, 0x2421, - 0x2441, 0x2441, 0x2461, 0x2481, - 0x2481, 0x24A1, 0x24C1, 0x24C1, - 0x24E1, 0x2501, 0x2501, 0x2521, /* 144 */ - 0x2541, 0x2541, 0x2561, 0x2561, - 0x2581, 0x25A1, 0x25A1, 0x25C1, - 0x25C1, 0x25E1, 0x2601, 0x2601, - 0x2621, 0x2621, 0x2641, 0x2641, /* 160 */ - 0x2661, 0x2661, 0x2681, 0x2681, - 0x26A1, 0x26A1, 0x26C1, 0x26C1, - 0x26E1, 0x26E1, 0x2701, 0x2701, - 0x2721, 0x2721, 0x2740, 0x2740, /* 176 */ - 0x2760, 0x2760, 0x2780, 0x2780, - 0x2780, 0x27A0, 0x27A0, 0x27C0, - 0x27C0, 0x27E0, 0x27E0, 0x27E0, - 0x2800, 0x2800, 0x2820, 0x2820, /* 192 */ - 0x2820, 0x2840, 0x2840, 0x2840, - 0x2860, 0x2860, 0x2880, 0x2880, - 0x2880, 0x28A0, 0x28A0, 0x28A0, - 0x28C0, 0x28C0, 0x28C0, 0x28E0, /* 208 */ - 0x28E0, 0x28E0, 0x2900, 0x2900, - 0x2900, 0x2920, 0x2920, 0x2920, - 0x2940, 0x2940, 0x2940, 0x2960, - 0x2960, 0x2960, 0x2960, 0x2980, /* 224 */ - 0x2980, 0x2980, 0x29A0, 0x29A0, - 0x29A0, 0x29A0, 0x29C0, 0x29C0, - 0x29C0, 0x29E0, 0x29E0, 0x29E0, - 0x29E0, 0x2A00, 0x2A00, 0x2A00, /* 240 */ - 0x2A00, 0x2A20, 0x2A20, 0x2A20, - 0x2A20, 0x2A40, 0x2A40, 0x2A40, - 0x2A40, 0x2A60, 0x2A60, 0x2A60, -}; - -const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE] = { - 0x0089, 0x02E9, 0x0409, 0x04E9, /* 0 */ - 0x05A9, 0x0669, 0x0709, 0x0789, - 0x0829, 0x08A9, 0x0929, 0x0989, - 0x0A09, 0x0A69, 0x0AC9, 0x0B29, - 0x0BA9, 0x0BE9, 0x0C49, 0x0CA9, /* 16 */ - 0x0D09, 0x0D69, 0x0DA9, 0x0E09, - 0x0E69, 0x0EA9, 0x0F09, 0x0F49, - 0x0FA9, 0x0FE9, 0x1029, 0x1089, - 0x10C9, 0x1109, 0x1169, 0x11A9, /* 32 */ - 0x11E9, 0x1229, 0x1289, 0x12C9, - 0x1309, 0x1349, 0x1389, 0x13C9, - 0x1409, 0x1449, 0x14A9, 0x14E9, - 0x1529, 0x1569, 0x15A9, 0x15E9, /* 48 */ - 0x1629, 0x1669, 0x16A9, 0x16E8, - 0x1728, 0x1768, 0x17A8, 0x17E8, - 0x1828, 0x1868, 0x18A8, 0x18E8, - 0x1928, 0x1968, 0x19A8, 0x19E8, /* 64 */ - 0x1A28, 0x1A68, 0x1AA8, 0x1AE8, - 0x1B28, 0x1B68, 0x1BA8, 0x1BE8, - 0x1C28, 0x1C68, 0x1CA8, 0x1CE8, - 0x1D28, 0x1D68, 0x1DC8, 0x1E08, /* 80 */ - 0x1E48, 0x1E88, 0x1EC8, 0x1F08, - 0x1F48, 0x1F88, 0x1FE8, 0x2028, - 0x2068, 0x20A8, 0x2108, 0x2148, - 0x2188, 0x21C8, 0x2228, 0x2268, /* 96 */ - 0x22C8, 0x2308, 0x2348, 0x23A8, - 0x23E8, 0x2448, 0x24A8, 0x24E8, - 0x2548, 0x25A8, 0x2608, 0x2668, - 0x26C8, 0x2728, 0x2787, 0x27E7, /* 112 */ - 0x2847, 0x28C7, 0x2947, 0x29A7, - 0x2A27, 0x2AC7, 0x2B47, 0x2BE7, - 0x2CA7, 0x2D67, 0x2E47, 0x2F67, - 0x3247, 0x3526, 0x3646, 0x3726, /* 128 */ - 0x3806, 0x38A6, 0x3946, 0x39E6, - 0x3A66, 0x3AE6, 0x3B66, 0x3BC6, - 0x3C45, 0x3CA5, 0x3D05, 0x3D85, - 0x3DE5, 0x3E45, 0x3EA5, 0x3EE5, /* 144 */ - 0x3F45, 0x3FA5, 0x4005, 0x4045, - 0x40A5, 0x40E5, 0x4145, 0x4185, - 0x41E5, 0x4225, 0x4265, 0x42C5, - 0x4305, 0x4345, 0x43A5, 0x43E5, /* 160 */ - 0x4424, 0x4464, 0x44C4, 0x4504, - 0x4544, 0x4584, 0x45C4, 0x4604, - 0x4644, 0x46A4, 0x46E4, 0x4724, - 0x4764, 0x47A4, 0x47E4, 0x4824, /* 176 */ - 0x4864, 0x48A4, 0x48E4, 0x4924, - 0x4964, 0x49A4, 0x49E4, 0x4A24, - 0x4A64, 0x4AA4, 0x4AE4, 0x4B23, - 0x4B63, 0x4BA3, 0x4BE3, 0x4C23, /* 192 */ - 0x4C63, 0x4CA3, 0x4CE3, 0x4D23, - 0x4D63, 0x4DA3, 0x4DE3, 0x4E23, - 0x4E63, 0x4EA3, 0x4EE3, 0x4F23, - 0x4F63, 0x4FC3, 0x5003, 0x5043, /* 208 */ - 0x5083, 0x50C3, 0x5103, 0x5143, - 0x5183, 0x51E2, 0x5222, 0x5262, - 0x52A2, 0x52E2, 0x5342, 0x5382, - 0x53C2, 0x5402, 0x5462, 0x54A2, /* 224 */ - 0x5502, 0x5542, 0x55A2, 0x55E2, - 0x5642, 0x5682, 0x56E2, 0x5722, - 0x5782, 0x57E1, 0x5841, 0x58A1, - 0x5901, 0x5961, 0x59C1, 0x5A21, /* 240 */ - 0x5AA1, 0x5B01, 0x5B81, 0x5BE1, - 0x5C61, 0x5D01, 0x5D80, 0x5E20, - 0x5EE0, 0x5FA0, 0x6080, 0x61C0, -}; - -const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE] = { - 0x0001, 0x0001, 0x0001, 0xFFFE, - 0xFFFE, 0x3FFF, 0x1000, 0x0393, -}; - -const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE] = { - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, - 0x4C4C, 0x4C4C, 0x4C4C, 0x2D36, -}; - -const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE] = { - 0x013C, 0x01F5, 0x031A, 0x0631, - 0x0001, 0x0001, 0x0001, 0x0001, -}; - -const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE] = { - 0x5484, 0x3C40, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, -}; - -const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE] = { - 0x6C77, 0x5162, 0x3B40, 0x3335, /* 0 */ - 0x2F2D, 0x2A2A, 0x2527, 0x1F21, - 0x1A1D, 0x1719, 0x1616, 0x1414, - 0x1414, 0x1400, 0x1414, 0x1614, - 0x1716, 0x1A19, 0x1F1D, 0x2521, /* 16 */ - 0x2A27, 0x2F2A, 0x332D, 0x3B35, - 0x5140, 0x6C62, 0x0077, -}; - -const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE] = { - 0xD8DD, 0xCBD4, 0xBCC0, 0XB6B7, /* 0 */ - 0xB2B0, 0xADAD, 0xA7A9, 0x9FA1, - 0x969B, 0x9195, 0x8F8F, 0x8A8A, - 0x8A8A, 0x8A00, 0x8A8A, 0x8F8A, - 0x918F, 0x9695, 0x9F9B, 0xA7A1, /* 16 */ - 0xADA9, 0xB2AD, 0xB6B0, 0xBCB7, - 0xCBC0, 0xD8D4, 0x00DD, -}; - -const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE] = { - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 0 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA400, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, /* 16 */ - 0xA4A4, 0xA4A4, 0xA4A4, 0xA4A4, - 0xA4A4, 0xA4A4, 0x00A4, -}; - -const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE] = { - 0x007A, 0x0075, 0x0071, 0x006C, /* 0 */ - 0x0067, 0x0063, 0x005E, 0x0059, - 0x0054, 0x0050, 0x004B, 0x0046, - 0x0042, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 16 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x0000, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, - 0x003D, 0x003D, 0x003D, 0x003D, /* 32 */ - 0x003D, 0x003D, 0x003D, 0x003D, - 0x0042, 0x0046, 0x004B, 0x0050, - 0x0054, 0x0059, 0x005E, 0x0063, - 0x0067, 0x006C, 0x0071, 0x0075, /* 48 */ - 0x007A, -}; - -const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE] = { - 0x00DE, 0x00DC, 0x00DA, 0x00D8, /* 0 */ - 0x00D6, 0x00D4, 0x00D2, 0x00CF, - 0x00CD, 0x00CA, 0x00C7, 0x00C4, - 0x00C1, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 16 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x0000, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00BE, 0x00BE, 0x00BE, 0x00BE, /* 32 */ - 0x00BE, 0x00BE, 0x00BE, 0x00BE, - 0x00C1, 0x00C4, 0x00C7, 0x00CA, - 0x00CD, 0x00CF, 0x00D2, 0x00D4, - 0x00D6, 0x00D8, 0x00DA, 0x00DC, /* 48 */ - 0x00DE, -}; - -/**** Helper functions to access the device Internal Lookup Tables ****/ - -void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val); - } -} - -void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA2, (val & 0xFFFF0000) >> 16); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, val & 0x0000FFFF); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA2, (val & 0xFFFF0000) >> 16); - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_DATA1, val & 0x0000FFFF); - } -} - -u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, offset); - return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_A_DATA1); - } else { - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_G_CTRL, offset); - return bcm43xx_phy_read(bcm, BCM43xx_PHY_ILT_G_DATA1); - } -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h b/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h deleted file mode 100644 index d7eaf5f25b7f..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_ilt.h +++ /dev/null @@ -1,33 +0,0 @@ -#ifndef BCM43xx_ILT_H_ -#define BCM43xx_ILT_H_ - -#define BCM43xx_ILT_ROTOR_SIZE 53 -extern const u32 bcm43xx_ilt_rotor[BCM43xx_ILT_ROTOR_SIZE]; -#define BCM43xx_ILT_RETARD_SIZE 53 -extern const u32 bcm43xx_ilt_retard[BCM43xx_ILT_RETARD_SIZE]; -#define BCM43xx_ILT_FINEFREQA_SIZE 256 -extern const u16 bcm43xx_ilt_finefreqa[BCM43xx_ILT_FINEFREQA_SIZE]; -#define BCM43xx_ILT_FINEFREQG_SIZE 256 -extern const u16 bcm43xx_ilt_finefreqg[BCM43xx_ILT_FINEFREQG_SIZE]; -#define BCM43xx_ILT_NOISEA2_SIZE 8 -extern const u16 bcm43xx_ilt_noisea2[BCM43xx_ILT_NOISEA2_SIZE]; -#define BCM43xx_ILT_NOISEA3_SIZE 8 -extern const u16 bcm43xx_ilt_noisea3[BCM43xx_ILT_NOISEA3_SIZE]; -#define BCM43xx_ILT_NOISEG1_SIZE 8 -extern const u16 bcm43xx_ilt_noiseg1[BCM43xx_ILT_NOISEG1_SIZE]; -#define BCM43xx_ILT_NOISEG2_SIZE 8 -extern const u16 bcm43xx_ilt_noiseg2[BCM43xx_ILT_NOISEG2_SIZE]; -#define BCM43xx_ILT_NOISESCALEG_SIZE 27 -extern const u16 bcm43xx_ilt_noisescaleg1[BCM43xx_ILT_NOISESCALEG_SIZE]; -extern const u16 bcm43xx_ilt_noisescaleg2[BCM43xx_ILT_NOISESCALEG_SIZE]; -extern const u16 bcm43xx_ilt_noisescaleg3[BCM43xx_ILT_NOISESCALEG_SIZE]; -#define BCM43xx_ILT_SIGMASQR_SIZE 53 -extern const u16 bcm43xx_ilt_sigmasqr1[BCM43xx_ILT_SIGMASQR_SIZE]; -extern const u16 bcm43xx_ilt_sigmasqr2[BCM43xx_ILT_SIGMASQR_SIZE]; - - -void bcm43xx_ilt_write(struct bcm43xx_private *bcm, u16 offset, u16 val); -void bcm43xx_ilt_write32(struct bcm43xx_private *bcm, u16 offset, u32 val); -u16 bcm43xx_ilt_read(struct bcm43xx_private *bcm, u16 offset); - -#endif /* BCM43xx_ILT_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c b/drivers/net/wireless/bcm43xx/bcm43xx_leds.c deleted file mode 100644 index cb51dc51cce6..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.c +++ /dev/null @@ -1,307 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx_leds.h" -#include "bcm43xx_radio.h" -#include "bcm43xx.h" - -#include - - -static void bcm43xx_led_changestate(struct bcm43xx_led *led) -{ - struct bcm43xx_private *bcm = led->bcm; - const int index = bcm43xx_led_index(led); - const u16 mask = (1 << index); - u16 ledctl; - - assert(index >= 0 && index < BCM43xx_NR_LEDS); - assert(led->blink_interval); - ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - ledctl = (ledctl & mask) ? (ledctl & ~mask) : (ledctl | mask); - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); -} - -static void bcm43xx_led_blink(unsigned long d) -{ - struct bcm43xx_led *led = (struct bcm43xx_led *)d; - struct bcm43xx_private *bcm = led->bcm; - unsigned long flags; - - spin_lock_irqsave(&bcm->leds_lock, flags); - if (led->blink_interval) { - bcm43xx_led_changestate(led); - mod_timer(&led->blink_timer, jiffies + led->blink_interval); - } - spin_unlock_irqrestore(&bcm->leds_lock, flags); -} - -static void bcm43xx_led_blink_start(struct bcm43xx_led *led, - unsigned long interval) -{ - if (led->blink_interval) - return; - led->blink_interval = interval; - bcm43xx_led_changestate(led); - led->blink_timer.expires = jiffies + interval; - add_timer(&led->blink_timer); -} - -static void bcm43xx_led_blink_stop(struct bcm43xx_led *led, int sync) -{ - struct bcm43xx_private *bcm = led->bcm; - const int index = bcm43xx_led_index(led); - u16 ledctl; - - if (!led->blink_interval) - return; - if (unlikely(sync)) - del_timer_sync(&led->blink_timer); - else - del_timer(&led->blink_timer); - led->blink_interval = 0; - - /* Make sure the LED is turned off. */ - assert(index >= 0 && index < BCM43xx_NR_LEDS); - ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - if (led->activelow) - ledctl |= (1 << index); - else - ledctl &= ~(1 << index); - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); -} - -static void bcm43xx_led_init_hardcoded(struct bcm43xx_private *bcm, - struct bcm43xx_led *led, - int led_index) -{ - /* This function is called, if the behaviour (and activelow) - * information for a LED is missing in the SPROM. - * We hardcode the behaviour values for various devices here. - * Note that the BCM43xx_LED_TEST_XXX behaviour values can - * be used to figure out which led is mapped to which index. - */ - - switch (led_index) { - case 0: - led->behaviour = BCM43xx_LED_ACTIVITY; - led->activelow = 1; - if (bcm->board_vendor == PCI_VENDOR_ID_COMPAQ) - led->behaviour = BCM43xx_LED_RADIO_ALL; - break; - case 1: - led->behaviour = BCM43xx_LED_RADIO_B; - if (bcm->board_vendor == PCI_VENDOR_ID_ASUSTEK) - led->behaviour = BCM43xx_LED_ASSOC; - break; - case 2: - led->behaviour = BCM43xx_LED_RADIO_A; - break; - case 3: - led->behaviour = BCM43xx_LED_OFF; - break; - default: - assert(0); - } -} - -int bcm43xx_leds_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_led *led; - u8 sprom[4]; - int i; - - sprom[0] = bcm->sprom.wl0gpio0; - sprom[1] = bcm->sprom.wl0gpio1; - sprom[2] = bcm->sprom.wl0gpio2; - sprom[3] = bcm->sprom.wl0gpio3; - - for (i = 0; i < BCM43xx_NR_LEDS; i++) { - led = &(bcm->leds[i]); - led->bcm = bcm; - setup_timer(&led->blink_timer, - bcm43xx_led_blink, - (unsigned long)led); - - if (sprom[i] == 0xFF) { - bcm43xx_led_init_hardcoded(bcm, led, i); - } else { - led->behaviour = sprom[i] & BCM43xx_LED_BEHAVIOUR; - led->activelow = !!(sprom[i] & BCM43xx_LED_ACTIVELOW); - } - } - - return 0; -} - -void bcm43xx_leds_exit(struct bcm43xx_private *bcm) -{ - struct bcm43xx_led *led; - int i; - - for (i = 0; i < BCM43xx_NR_LEDS; i++) { - led = &(bcm->leds[i]); - bcm43xx_led_blink_stop(led, 1); - } - bcm43xx_leds_switch_all(bcm, 0); -} - -void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity) -{ - struct bcm43xx_led *led; - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - const int transferring = (jiffies - bcm->stats.last_tx) < BCM43xx_LED_XFER_THRES; - int i, turn_on; - unsigned long interval = 0; - u16 ledctl; - unsigned long flags; - - spin_lock_irqsave(&bcm->leds_lock, flags); - ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - for (i = 0; i < BCM43xx_NR_LEDS; i++) { - led = &(bcm->leds[i]); - - turn_on = 0; - switch (led->behaviour) { - case BCM43xx_LED_INACTIVE: - continue; - case BCM43xx_LED_OFF: - case BCM43xx_LED_BCM4303_3: - break; - case BCM43xx_LED_ON: - turn_on = 1; - break; - case BCM43xx_LED_ACTIVITY: - case BCM43xx_LED_BCM4303_0: - turn_on = activity; - break; - case BCM43xx_LED_RADIO_ALL: - turn_on = radio->enabled && bcm43xx_is_hw_radio_enabled(bcm); - break; - case BCM43xx_LED_RADIO_A: - case BCM43xx_LED_BCM4303_2: - turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) && - phy->type == BCM43xx_PHYTYPE_A); - break; - case BCM43xx_LED_RADIO_B: - case BCM43xx_LED_BCM4303_1: - turn_on = (radio->enabled && bcm43xx_is_hw_radio_enabled(bcm) && - (phy->type == BCM43xx_PHYTYPE_B || - phy->type == BCM43xx_PHYTYPE_G)); - break; - case BCM43xx_LED_MODE_BG: - if (phy->type == BCM43xx_PHYTYPE_G && bcm43xx_is_hw_radio_enabled(bcm) && - 1/*FIXME: using G rates.*/) - turn_on = 1; - break; - case BCM43xx_LED_TRANSFER: - if (transferring) - bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM); - else - bcm43xx_led_blink_stop(led, 0); - continue; - case BCM43xx_LED_APTRANSFER: - if (bcm->ieee->iw_mode == IW_MODE_MASTER) { - if (transferring) { - interval = BCM43xx_LEDBLINK_FAST; - turn_on = 1; - } - } else { - turn_on = 1; - if (0/*TODO: not assoc*/) - interval = BCM43xx_LEDBLINK_SLOW; - else if (transferring) - interval = BCM43xx_LEDBLINK_FAST; - else - turn_on = 0; - } - if (turn_on) - bcm43xx_led_blink_start(led, interval); - else - bcm43xx_led_blink_stop(led, 0); - continue; - case BCM43xx_LED_WEIRD: - //TODO - break; - case BCM43xx_LED_ASSOC: - if (bcm->softmac->associnfo.associated) - turn_on = 1; - break; -#ifdef CONFIG_BCM43XX_DEBUG - case BCM43xx_LED_TEST_BLINKSLOW: - bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_SLOW); - continue; - case BCM43xx_LED_TEST_BLINKMEDIUM: - bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_MEDIUM); - continue; - case BCM43xx_LED_TEST_BLINKFAST: - bcm43xx_led_blink_start(led, BCM43xx_LEDBLINK_FAST); - continue; -#endif /* CONFIG_BCM43XX_DEBUG */ - default: - dprintkl(KERN_INFO PFX "Bad value in leds_update," - " led->behaviour: 0x%x\n", led->behaviour); - }; - - if (led->activelow) - turn_on = !turn_on; - if (turn_on) - ledctl |= (1 << i); - else - ledctl &= ~(1 << i); - } - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); - spin_unlock_irqrestore(&bcm->leds_lock, flags); -} - -void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on) -{ - struct bcm43xx_led *led; - u16 ledctl; - int i; - int bit_on; - unsigned long flags; - - spin_lock_irqsave(&bcm->leds_lock, flags); - ledctl = bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_CONTROL); - for (i = 0; i < BCM43xx_NR_LEDS; i++) { - led = &(bcm->leds[i]); - if (led->behaviour == BCM43xx_LED_INACTIVE) - continue; - if (on) - bit_on = led->activelow ? 0 : 1; - else - bit_on = led->activelow ? 1 : 0; - if (bit_on) - ledctl |= (1 << i); - else - ledctl &= ~(1 << i); - } - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_CONTROL, ledctl); - spin_unlock_irqrestore(&bcm->leds_lock, flags); -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h b/drivers/net/wireless/bcm43xx/bcm43xx_leds.h deleted file mode 100644 index 811e14a81198..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_leds.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef BCM43xx_LEDS_H_ -#define BCM43xx_LEDS_H_ - -#include -#include - - -struct bcm43xx_led { - u8 behaviour:7; - u8 activelow:1; - - struct bcm43xx_private *bcm; - struct timer_list blink_timer; - unsigned long blink_interval; -}; -#define bcm43xx_led_index(led) ((int)((led) - (led)->bcm->leds)) - -/* Delay between state changes when blinking in jiffies */ -#define BCM43xx_LEDBLINK_SLOW (HZ / 1) -#define BCM43xx_LEDBLINK_MEDIUM (HZ / 4) -#define BCM43xx_LEDBLINK_FAST (HZ / 8) - -#define BCM43xx_LED_XFER_THRES (HZ / 100) - -#define BCM43xx_LED_BEHAVIOUR 0x7F -#define BCM43xx_LED_ACTIVELOW 0x80 -enum { /* LED behaviour values */ - BCM43xx_LED_OFF, - BCM43xx_LED_ON, - BCM43xx_LED_ACTIVITY, - BCM43xx_LED_RADIO_ALL, - BCM43xx_LED_RADIO_A, - BCM43xx_LED_RADIO_B, - BCM43xx_LED_MODE_BG, - BCM43xx_LED_TRANSFER, - BCM43xx_LED_APTRANSFER, - BCM43xx_LED_WEIRD,//FIXME - BCM43xx_LED_ASSOC, - BCM43xx_LED_INACTIVE, - - /* Behaviour values for testing. - * With these values it is easier to figure out - * the real behaviour of leds, in case the SPROM - * is missing information. - */ - BCM43xx_LED_TEST_BLINKSLOW, - BCM43xx_LED_TEST_BLINKMEDIUM, - BCM43xx_LED_TEST_BLINKFAST, - - /* Misc values for BCM4303 */ - BCM43xx_LED_BCM4303_0 = 0x2B, - BCM43xx_LED_BCM4303_1 = 0x78, - BCM43xx_LED_BCM4303_2 = 0x2E, - BCM43xx_LED_BCM4303_3 = 0x19, -}; - -int bcm43xx_leds_init(struct bcm43xx_private *bcm); -void bcm43xx_leds_exit(struct bcm43xx_private *bcm); -void bcm43xx_leds_update(struct bcm43xx_private *bcm, int activity); -void bcm43xx_leds_switch_all(struct bcm43xx_private *bcm, int on); - -#endif /* BCM43xx_LEDS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.c b/drivers/net/wireless/bcm43xx/bcm43xx_main.c deleted file mode 100644 index b96a325b6ec8..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.c +++ /dev/null @@ -1,4281 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bcm43xx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_debugfs.h" -#include "bcm43xx_radio.h" -#include "bcm43xx_phy.h" -#include "bcm43xx_dma.h" -#include "bcm43xx_pio.h" -#include "bcm43xx_power.h" -#include "bcm43xx_wx.h" -#include "bcm43xx_ethtool.h" -#include "bcm43xx_xmit.h" -#include "bcm43xx_sysfs.h" - - -MODULE_DESCRIPTION("Broadcom BCM43xx wireless driver"); -MODULE_AUTHOR("Martin Langer"); -MODULE_AUTHOR("Stefano Brivio"); -MODULE_AUTHOR("Michael Buesch"); -MODULE_LICENSE("GPL"); - -#if defined(CONFIG_BCM43XX_DMA) && defined(CONFIG_BCM43XX_PIO) -static int modparam_pio; -module_param_named(pio, modparam_pio, int, 0444); -MODULE_PARM_DESC(pio, "enable(1) / disable(0) PIO mode"); -#elif defined(CONFIG_BCM43XX_DMA) -# define modparam_pio 0 -#elif defined(CONFIG_BCM43XX_PIO) -# define modparam_pio 1 -#endif - -static int modparam_bad_frames_preempt; -module_param_named(bad_frames_preempt, modparam_bad_frames_preempt, int, 0444); -MODULE_PARM_DESC(bad_frames_preempt, "enable(1) / disable(0) Bad Frames Preemption"); - -static int modparam_short_retry = BCM43xx_DEFAULT_SHORT_RETRY_LIMIT; -module_param_named(short_retry, modparam_short_retry, int, 0444); -MODULE_PARM_DESC(short_retry, "Short-Retry-Limit (0 - 15)"); - -static int modparam_long_retry = BCM43xx_DEFAULT_LONG_RETRY_LIMIT; -module_param_named(long_retry, modparam_long_retry, int, 0444); -MODULE_PARM_DESC(long_retry, "Long-Retry-Limit (0 - 15)"); - -static int modparam_locale = -1; -module_param_named(locale, modparam_locale, int, 0444); -MODULE_PARM_DESC(country, "Select LocaleCode 0-11 (For travelers)"); - -static int modparam_noleds; -module_param_named(noleds, modparam_noleds, int, 0444); -MODULE_PARM_DESC(noleds, "Turn off all LED activity"); - -static char modparam_fwpostfix[64]; -module_param_string(fwpostfix, modparam_fwpostfix, 64, 0444); -MODULE_PARM_DESC(fwpostfix, "Postfix for .fw files. Useful for using multiple firmware image versions."); - - -/* If you want to debug with just a single device, enable this, - * where the string is the pci device ID (as given by the kernel's - * pci_name function) of the device to be used. - */ -//#define DEBUG_SINGLE_DEVICE_ONLY "0001:11:00.0" - -/* If you want to enable printing of each MMIO access, enable this. */ -//#define DEBUG_ENABLE_MMIO_PRINT - -/* If you want to enable printing of MMIO access within - * ucode/pcm upload, initvals write, enable this. - */ -//#define DEBUG_ENABLE_UCODE_MMIO_PRINT - -/* If you want to enable printing of PCI Config Space access, enable this */ -//#define DEBUG_ENABLE_PCILOG - - -/* Detailed list maintained at: - * http://openfacts.berlios.de/index-en.phtml?title=Bcm43xxDevices - */ - static struct pci_device_id bcm43xx_pci_tbl[] = { - /* Broadcom 4303 802.11b */ - { PCI_VENDOR_ID_BROADCOM, 0x4301, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4307 802.11b */ - { PCI_VENDOR_ID_BROADCOM, 0x4307, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4311 802.11(a)/b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4311, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4312 802.11a/b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4312, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4318 802.11b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4318, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4319 802.11a/b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4319, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4306 802.11b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4306 802.11a */ -// { PCI_VENDOR_ID_BROADCOM, 0x4321, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 4309 802.11a/b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4324, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - /* Broadcom 43XG 802.11b/g */ - { PCI_VENDOR_ID_BROADCOM, 0x4325, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { 0 }, -}; -MODULE_DEVICE_TABLE(pci, bcm43xx_pci_tbl); - -static void bcm43xx_ram_write(struct bcm43xx_private *bcm, u16 offset, u32 val) -{ - u32 status; - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if (!(status & BCM43xx_SBF_XFER_REG_BYTESWAP)) - val = swab32(val); - - bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_CONTROL, offset); - mmiowb(); - bcm43xx_write32(bcm, BCM43xx_MMIO_RAM_DATA, val); -} - -static inline -void bcm43xx_shm_control_word(struct bcm43xx_private *bcm, - u16 routing, u16 offset) -{ - u32 control; - - /* "offset" is the WORD offset. */ - - control = routing; - control <<= 16; - control |= offset; - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_CONTROL, control); -} - -u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm, - u16 routing, u16 offset) -{ - u32 ret; - - if (routing == BCM43xx_SHM_SHARED) { - if (offset & 0x0003) { - /* Unaligned access */ - bcm43xx_shm_control_word(bcm, routing, offset >> 2); - ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED); - ret <<= 16; - bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); - ret |= bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA); - - return ret; - } - offset >>= 2; - } - bcm43xx_shm_control_word(bcm, routing, offset); - ret = bcm43xx_read32(bcm, BCM43xx_MMIO_SHM_DATA); - - return ret; -} - -u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm, - u16 routing, u16 offset) -{ - u16 ret; - - if (routing == BCM43xx_SHM_SHARED) { - if (offset & 0x0003) { - /* Unaligned access */ - bcm43xx_shm_control_word(bcm, routing, offset >> 2); - ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED); - - return ret; - } - offset >>= 2; - } - bcm43xx_shm_control_word(bcm, routing, offset); - ret = bcm43xx_read16(bcm, BCM43xx_MMIO_SHM_DATA); - - return ret; -} - -void bcm43xx_shm_write32(struct bcm43xx_private *bcm, - u16 routing, u16 offset, - u32 value) -{ - if (routing == BCM43xx_SHM_SHARED) { - if (offset & 0x0003) { - /* Unaligned access */ - bcm43xx_shm_control_word(bcm, routing, offset >> 2); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, - (value >> 16) & 0xffff); - mmiowb(); - bcm43xx_shm_control_word(bcm, routing, (offset >> 2) + 1); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, - value & 0xffff); - return; - } - offset >>= 2; - } - bcm43xx_shm_control_word(bcm, routing, offset); - mmiowb(); - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, value); -} - -void bcm43xx_shm_write16(struct bcm43xx_private *bcm, - u16 routing, u16 offset, - u16 value) -{ - if (routing == BCM43xx_SHM_SHARED) { - if (offset & 0x0003) { - /* Unaligned access */ - bcm43xx_shm_control_word(bcm, routing, offset >> 2); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA_UNALIGNED, - value); - return; - } - offset >>= 2; - } - bcm43xx_shm_control_word(bcm, routing, offset); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_SHM_DATA, value); -} - -void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf) -{ - /* We need to be careful. As we read the TSF from multiple - * registers, we should take care of register overflows. - * In theory, the whole tsf read process should be atomic. - * We try to be atomic here, by restaring the read process, - * if any of the high registers changed (overflew). - */ - if (bcm->current_core->rev >= 3) { - u32 low, high, high2; - - do { - high = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH); - low = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW); - high2 = bcm43xx_read32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH); - } while (unlikely(high != high2)); - - *tsf = high; - *tsf <<= 32; - *tsf |= low; - } else { - u64 tmp; - u16 v0, v1, v2, v3; - u16 test1, test2, test3; - - do { - v3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3); - v2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2); - v1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1); - v0 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_0); - - test3 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_3); - test2 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_2); - test1 = bcm43xx_read16(bcm, BCM43xx_MMIO_TSF_1); - } while (v3 != test3 || v2 != test2 || v1 != test1); - - *tsf = v3; - *tsf <<= 48; - tmp = v2; - tmp <<= 32; - *tsf |= tmp; - tmp = v1; - tmp <<= 16; - *tsf |= tmp; - *tsf |= v0; - } -} - -void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf) -{ - u32 status; - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status |= BCM43xx_SBF_TIME_UPDATE; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - mmiowb(); - - /* Be careful with the in-progress timer. - * First zero out the low register, so we have a full - * register-overflow duration to complete the operation. - */ - if (bcm->current_core->rev >= 3) { - u32 lo = (tsf & 0x00000000FFFFFFFFULL); - u32 hi = (tsf & 0xFFFFFFFF00000000ULL) >> 32; - - bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, 0); - mmiowb(); - bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_HIGH, hi); - mmiowb(); - bcm43xx_write32(bcm, BCM43xx_MMIO_REV3PLUS_TSF_LOW, lo); - } else { - u16 v0 = (tsf & 0x000000000000FFFFULL); - u16 v1 = (tsf & 0x00000000FFFF0000ULL) >> 16; - u16 v2 = (tsf & 0x0000FFFF00000000ULL) >> 32; - u16 v3 = (tsf & 0xFFFF000000000000ULL) >> 48; - - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, 0); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_3, v3); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_2, v2); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_1, v1); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_TSF_0, v0); - } - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status &= ~BCM43xx_SBF_TIME_UPDATE; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); -} - -static -void bcm43xx_macfilter_set(struct bcm43xx_private *bcm, - u16 offset, - const u8 *mac) -{ - u16 data; - - offset |= 0x0020; - bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_CONTROL, offset); - - data = mac[0]; - data |= mac[1] << 8; - bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); - data = mac[2]; - data |= mac[3] << 8; - bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); - data = mac[4]; - data |= mac[5] << 8; - bcm43xx_write16(bcm, BCM43xx_MMIO_MACFILTER_DATA, data); -} - -static void bcm43xx_macfilter_clear(struct bcm43xx_private *bcm, - u16 offset) -{ - const u8 zero_addr[ETH_ALEN] = { 0 }; - - bcm43xx_macfilter_set(bcm, offset, zero_addr); -} - -static void bcm43xx_write_mac_bssid_templates(struct bcm43xx_private *bcm) -{ - const u8 *mac = (const u8 *)(bcm->net_dev->dev_addr); - const u8 *bssid = (const u8 *)(bcm->ieee->bssid); - u8 mac_bssid[ETH_ALEN * 2]; - int i; - - memcpy(mac_bssid, mac, ETH_ALEN); - memcpy(mac_bssid + ETH_ALEN, bssid, ETH_ALEN); - - /* Write our MAC address and BSSID to template ram */ - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x20 + i, *((u32 *)(mac_bssid + i))); - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x78 + i, *((u32 *)(mac_bssid + i))); - for (i = 0; i < ARRAY_SIZE(mac_bssid); i += sizeof(u32)) - bcm43xx_ram_write(bcm, 0x478 + i, *((u32 *)(mac_bssid + i))); -} - -//FIXME: Well, we should probably call them from somewhere. -#if 0 -static void bcm43xx_set_slot_time(struct bcm43xx_private *bcm, u16 slot_time) -{ - /* slot_time is in usec. */ - if (bcm43xx_current_phy(bcm)->type != BCM43xx_PHYTYPE_G) - return; - bcm43xx_write16(bcm, 0x684, 510 + slot_time); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0010, slot_time); -} - -static void bcm43xx_short_slot_timing_enable(struct bcm43xx_private *bcm) -{ - bcm43xx_set_slot_time(bcm, 9); -} - -static void bcm43xx_short_slot_timing_disable(struct bcm43xx_private *bcm) -{ - bcm43xx_set_slot_time(bcm, 20); -} -#endif - -/* FIXME: To get the MAC-filter working, we need to implement the - * following functions (and rename them :) - */ -#if 0 -static void bcm43xx_disassociate(struct bcm43xx_private *bcm) -{ - bcm43xx_mac_suspend(bcm); - bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); - - bcm43xx_ram_write(bcm, 0x0026, 0x0000); - bcm43xx_ram_write(bcm, 0x0028, 0x0000); - bcm43xx_ram_write(bcm, 0x007E, 0x0000); - bcm43xx_ram_write(bcm, 0x0080, 0x0000); - bcm43xx_ram_write(bcm, 0x047E, 0x0000); - bcm43xx_ram_write(bcm, 0x0480, 0x0000); - - if (bcm->current_core->rev < 3) { - bcm43xx_write16(bcm, 0x0610, 0x8000); - bcm43xx_write16(bcm, 0x060E, 0x0000); - } else - bcm43xx_write32(bcm, 0x0188, 0x80000000); - - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); - - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_G && - ieee80211_is_ofdm_rate(bcm->softmac->txrates.default_rate)) - bcm43xx_short_slot_timing_enable(bcm); - - bcm43xx_mac_enable(bcm); -} - -static void bcm43xx_associate(struct bcm43xx_private *bcm, - const u8 *mac) -{ - memcpy(bcm->ieee->bssid, mac, ETH_ALEN); - - bcm43xx_mac_suspend(bcm); - bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_ASSOC, mac); - bcm43xx_write_mac_bssid_templates(bcm); - bcm43xx_mac_enable(bcm); -} -#endif - -/* Enable a Generic IRQ. "mask" is the mask of which IRQs to enable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 bcm43xx_interrupt_enable(struct bcm43xx_private *bcm, u32 mask) -{ - u32 old_mask; - - old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask | mask); - - return old_mask; -} - -/* Disable a Generic IRQ. "mask" is the mask of which IRQs to disable. - * Returns the _previously_ enabled IRQ mask. - */ -static inline u32 bcm43xx_interrupt_disable(struct bcm43xx_private *bcm, u32 mask) -{ - u32 old_mask; - - old_mask = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK, old_mask & ~mask); - - return old_mask; -} - -/* Synchronize IRQ top- and bottom-half. - * IRQs must be masked before calling this. - * This must not be called with the irq_lock held. - */ -static void bcm43xx_synchronize_irq(struct bcm43xx_private *bcm) -{ - synchronize_irq(bcm->irq); - tasklet_disable(&bcm->isr_tasklet); -} - -/* Make sure we don't receive more data from the device. */ -static int bcm43xx_disable_interrupts_sync(struct bcm43xx_private *bcm) -{ - unsigned long flags; - - spin_lock_irqsave(&bcm->irq_lock, flags); - if (unlikely(bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED)) { - spin_unlock_irqrestore(&bcm->irq_lock, flags); - return -EBUSY; - } - bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); /* flush */ - spin_unlock_irqrestore(&bcm->irq_lock, flags); - bcm43xx_synchronize_irq(bcm); - - return 0; -} - -static int bcm43xx_read_radioinfo(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u32 radio_id; - u16 manufact; - u16 version; - u8 revision; - - if (bcm->chip_id == 0x4317) { - if (bcm->chip_rev == 0x00) - radio_id = 0x3205017F; - else if (bcm->chip_rev == 0x01) - radio_id = 0x4205017F; - else - radio_id = 0x5205017F; - } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID); - radio_id = bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_HIGH); - radio_id <<= 16; - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, BCM43xx_RADIOCTL_ID); - radio_id |= bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW); - } - - manufact = (radio_id & 0x00000FFF); - version = (radio_id & 0x0FFFF000) >> 12; - revision = (radio_id & 0xF0000000) >> 28; - - dprintk(KERN_INFO PFX "Detected Radio: ID: %x (Manuf: %x Ver: %x Rev: %x)\n", - radio_id, manufact, version, revision); - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - if ((version != 0x2060) || (revision != 1) || (manufact != 0x17f)) - goto err_unsupported_radio; - break; - case BCM43xx_PHYTYPE_B: - if ((version & 0xFFF0) != 0x2050) - goto err_unsupported_radio; - break; - case BCM43xx_PHYTYPE_G: - if (version != 0x2050) - goto err_unsupported_radio; - break; - } - - radio->manufact = manufact; - radio->version = version; - radio->revision = revision; - - if (phy->type == BCM43xx_PHYTYPE_A) - radio->txpower_desired = bcm->sprom.maxpower_aphy; - else - radio->txpower_desired = bcm->sprom.maxpower_bgphy; - - return 0; - -err_unsupported_radio: - printk(KERN_ERR PFX "Unsupported Radio connected to the PHY!\n"); - return -ENODEV; -} - -static const char * bcm43xx_locale_iso(u8 locale) -{ - /* ISO 3166-1 country codes. - * Note that there aren't ISO 3166-1 codes for - * all or locales. (Not all locales are countries) - */ - switch (locale) { - case BCM43xx_LOCALE_WORLD: - case BCM43xx_LOCALE_ALL: - return "XX"; - case BCM43xx_LOCALE_THAILAND: - return "TH"; - case BCM43xx_LOCALE_ISRAEL: - return "IL"; - case BCM43xx_LOCALE_JORDAN: - return "JO"; - case BCM43xx_LOCALE_CHINA: - return "CN"; - case BCM43xx_LOCALE_JAPAN: - case BCM43xx_LOCALE_JAPAN_HIGH: - return "JP"; - case BCM43xx_LOCALE_USA_CANADA_ANZ: - case BCM43xx_LOCALE_USA_LOW: - return "US"; - case BCM43xx_LOCALE_EUROPE: - return "EU"; - case BCM43xx_LOCALE_NONE: - return " "; - } - assert(0); - return " "; -} - -static const char * bcm43xx_locale_string(u8 locale) -{ - switch (locale) { - case BCM43xx_LOCALE_WORLD: - return "World"; - case BCM43xx_LOCALE_THAILAND: - return "Thailand"; - case BCM43xx_LOCALE_ISRAEL: - return "Israel"; - case BCM43xx_LOCALE_JORDAN: - return "Jordan"; - case BCM43xx_LOCALE_CHINA: - return "China"; - case BCM43xx_LOCALE_JAPAN: - return "Japan"; - case BCM43xx_LOCALE_USA_CANADA_ANZ: - return "USA/Canada/ANZ"; - case BCM43xx_LOCALE_EUROPE: - return "Europe"; - case BCM43xx_LOCALE_USA_LOW: - return "USAlow"; - case BCM43xx_LOCALE_JAPAN_HIGH: - return "JapanHigh"; - case BCM43xx_LOCALE_ALL: - return "All"; - case BCM43xx_LOCALE_NONE: - return "None"; - } - assert(0); - return ""; -} - -static inline u8 bcm43xx_crc8(u8 crc, u8 data) -{ - static const u8 t[] = { - 0x00, 0xF7, 0xB9, 0x4E, 0x25, 0xD2, 0x9C, 0x6B, - 0x4A, 0xBD, 0xF3, 0x04, 0x6F, 0x98, 0xD6, 0x21, - 0x94, 0x63, 0x2D, 0xDA, 0xB1, 0x46, 0x08, 0xFF, - 0xDE, 0x29, 0x67, 0x90, 0xFB, 0x0C, 0x42, 0xB5, - 0x7F, 0x88, 0xC6, 0x31, 0x5A, 0xAD, 0xE3, 0x14, - 0x35, 0xC2, 0x8C, 0x7B, 0x10, 0xE7, 0xA9, 0x5E, - 0xEB, 0x1C, 0x52, 0xA5, 0xCE, 0x39, 0x77, 0x80, - 0xA1, 0x56, 0x18, 0xEF, 0x84, 0x73, 0x3D, 0xCA, - 0xFE, 0x09, 0x47, 0xB0, 0xDB, 0x2C, 0x62, 0x95, - 0xB4, 0x43, 0x0D, 0xFA, 0x91, 0x66, 0x28, 0xDF, - 0x6A, 0x9D, 0xD3, 0x24, 0x4F, 0xB8, 0xF6, 0x01, - 0x20, 0xD7, 0x99, 0x6E, 0x05, 0xF2, 0xBC, 0x4B, - 0x81, 0x76, 0x38, 0xCF, 0xA4, 0x53, 0x1D, 0xEA, - 0xCB, 0x3C, 0x72, 0x85, 0xEE, 0x19, 0x57, 0xA0, - 0x15, 0xE2, 0xAC, 0x5B, 0x30, 0xC7, 0x89, 0x7E, - 0x5F, 0xA8, 0xE6, 0x11, 0x7A, 0x8D, 0xC3, 0x34, - 0xAB, 0x5C, 0x12, 0xE5, 0x8E, 0x79, 0x37, 0xC0, - 0xE1, 0x16, 0x58, 0xAF, 0xC4, 0x33, 0x7D, 0x8A, - 0x3F, 0xC8, 0x86, 0x71, 0x1A, 0xED, 0xA3, 0x54, - 0x75, 0x82, 0xCC, 0x3B, 0x50, 0xA7, 0xE9, 0x1E, - 0xD4, 0x23, 0x6D, 0x9A, 0xF1, 0x06, 0x48, 0xBF, - 0x9E, 0x69, 0x27, 0xD0, 0xBB, 0x4C, 0x02, 0xF5, - 0x40, 0xB7, 0xF9, 0x0E, 0x65, 0x92, 0xDC, 0x2B, - 0x0A, 0xFD, 0xB3, 0x44, 0x2F, 0xD8, 0x96, 0x61, - 0x55, 0xA2, 0xEC, 0x1B, 0x70, 0x87, 0xC9, 0x3E, - 0x1F, 0xE8, 0xA6, 0x51, 0x3A, 0xCD, 0x83, 0x74, - 0xC1, 0x36, 0x78, 0x8F, 0xE4, 0x13, 0x5D, 0xAA, - 0x8B, 0x7C, 0x32, 0xC5, 0xAE, 0x59, 0x17, 0xE0, - 0x2A, 0xDD, 0x93, 0x64, 0x0F, 0xF8, 0xB6, 0x41, - 0x60, 0x97, 0xD9, 0x2E, 0x45, 0xB2, 0xFC, 0x0B, - 0xBE, 0x49, 0x07, 0xF0, 0x9B, 0x6C, 0x22, 0xD5, - 0xF4, 0x03, 0x4D, 0xBA, 0xD1, 0x26, 0x68, 0x9F, - }; - return t[crc ^ data]; -} - -static u8 bcm43xx_sprom_crc(const u16 *sprom) -{ - int word; - u8 crc = 0xFF; - - for (word = 0; word < BCM43xx_SPROM_SIZE - 1; word++) { - crc = bcm43xx_crc8(crc, sprom[word] & 0x00FF); - crc = bcm43xx_crc8(crc, (sprom[word] & 0xFF00) >> 8); - } - crc = bcm43xx_crc8(crc, sprom[BCM43xx_SPROM_VERSION] & 0x00FF); - crc ^= 0xFF; - - return crc; -} - -int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom) -{ - int i; - u8 crc, expected_crc; - - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) - sprom[i] = bcm43xx_read16(bcm, BCM43xx_SPROM_BASE + (i * 2)); - /* CRC-8 check. */ - crc = bcm43xx_sprom_crc(sprom); - expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; - if (crc != expected_crc) { - printk(KERN_WARNING PFX "WARNING: Invalid SPROM checksum " - "(0x%02X, expected: 0x%02X)\n", - crc, expected_crc); - return -EINVAL; - } - - return 0; -} - -int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom) -{ - int i, err; - u8 crc, expected_crc; - u32 spromctl; - - /* CRC-8 validation of the input data. */ - crc = bcm43xx_sprom_crc(sprom); - expected_crc = (sprom[BCM43xx_SPROM_VERSION] & 0xFF00) >> 8; - if (crc != expected_crc) { - printk(KERN_ERR PFX "SPROM input data: Invalid CRC\n"); - return -EINVAL; - } - - printk(KERN_INFO PFX "Writing SPROM. Do NOT turn off the power! Please stand by...\n"); - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_SPROMCTL, &spromctl); - if (err) - goto err_ctlreg; - spromctl |= 0x10; /* SPROM WRITE enable. */ - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); - if (err) - goto err_ctlreg; - /* We must burn lots of CPU cycles here, but that does not - * really matter as one does not write the SPROM every other minute... - */ - printk(KERN_INFO PFX "[ 0%%"); - mdelay(500); - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { - if (i == 16) - printk("25%%"); - else if (i == 32) - printk("50%%"); - else if (i == 48) - printk("75%%"); - else if (i % 2) - printk("."); - bcm43xx_write16(bcm, BCM43xx_SPROM_BASE + (i * 2), sprom[i]); - mmiowb(); - mdelay(20); - } - spromctl &= ~0x10; /* SPROM WRITE enable. */ - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_SPROMCTL, spromctl); - if (err) - goto err_ctlreg; - mdelay(500); - printk("100%% ]\n"); - printk(KERN_INFO PFX "SPROM written.\n"); - bcm43xx_controller_restart(bcm, "SPROM update"); - - return 0; -err_ctlreg: - printk(KERN_ERR PFX "Could not access SPROM control register.\n"); - return -ENODEV; -} - -static int bcm43xx_sprom_extract(struct bcm43xx_private *bcm) -{ - u16 value; - u16 *sprom; - - sprom = kzalloc(BCM43xx_SPROM_SIZE * sizeof(u16), - GFP_KERNEL); - if (!sprom) { - printk(KERN_ERR PFX "sprom_extract OOM\n"); - return -ENOMEM; - } - bcm43xx_sprom_read(bcm, sprom); - - /* boardflags2 */ - value = sprom[BCM43xx_SPROM_BOARDFLAGS2]; - bcm->sprom.boardflags2 = value; - - /* il0macaddr */ - value = sprom[BCM43xx_SPROM_IL0MACADDR + 0]; - *(((__be16 *)bcm->sprom.il0macaddr) + 0) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_IL0MACADDR + 1]; - *(((__be16 *)bcm->sprom.il0macaddr) + 1) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_IL0MACADDR + 2]; - *(((__be16 *)bcm->sprom.il0macaddr) + 2) = cpu_to_be16(value); - - /* et0macaddr */ - value = sprom[BCM43xx_SPROM_ET0MACADDR + 0]; - *(((__be16 *)bcm->sprom.et0macaddr) + 0) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_ET0MACADDR + 1]; - *(((__be16 *)bcm->sprom.et0macaddr) + 1) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_ET0MACADDR + 2]; - *(((__be16 *)bcm->sprom.et0macaddr) + 2) = cpu_to_be16(value); - - /* et1macaddr */ - value = sprom[BCM43xx_SPROM_ET1MACADDR + 0]; - *(((__be16 *)bcm->sprom.et1macaddr) + 0) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_ET1MACADDR + 1]; - *(((__be16 *)bcm->sprom.et1macaddr) + 1) = cpu_to_be16(value); - value = sprom[BCM43xx_SPROM_ET1MACADDR + 2]; - *(((__be16 *)bcm->sprom.et1macaddr) + 2) = cpu_to_be16(value); - - /* ethernet phy settings */ - value = sprom[BCM43xx_SPROM_ETHPHY]; - bcm->sprom.et0phyaddr = (value & 0x001F); - bcm->sprom.et1phyaddr = (value & 0x03E0) >> 5; - - /* boardrev, antennas, locale */ - value = sprom[BCM43xx_SPROM_BOARDREV]; - bcm->sprom.boardrev = (value & 0x00FF); - bcm->sprom.locale = (value & 0x0F00) >> 8; - bcm->sprom.antennas_aphy = (value & 0x3000) >> 12; - bcm->sprom.antennas_bgphy = (value & 0xC000) >> 14; - if (modparam_locale != -1) { - if (modparam_locale >= 0 && modparam_locale <= 11) { - bcm->sprom.locale = modparam_locale; - printk(KERN_WARNING PFX "Operating with modified " - "LocaleCode %u (%s)\n", - bcm->sprom.locale, - bcm43xx_locale_string(bcm->sprom.locale)); - } else { - printk(KERN_WARNING PFX "Module parameter \"locale\" " - "invalid value. (0 - 11)\n"); - } - } - - /* pa0b* */ - value = sprom[BCM43xx_SPROM_PA0B0]; - bcm->sprom.pa0b0 = value; - value = sprom[BCM43xx_SPROM_PA0B1]; - bcm->sprom.pa0b1 = value; - value = sprom[BCM43xx_SPROM_PA0B2]; - bcm->sprom.pa0b2 = value; - - /* wl0gpio* */ - value = sprom[BCM43xx_SPROM_WL0GPIO0]; - if (value == 0x0000) - value = 0xFFFF; - bcm->sprom.wl0gpio0 = value & 0x00FF; - bcm->sprom.wl0gpio1 = (value & 0xFF00) >> 8; - value = sprom[BCM43xx_SPROM_WL0GPIO2]; - if (value == 0x0000) - value = 0xFFFF; - bcm->sprom.wl0gpio2 = value & 0x00FF; - bcm->sprom.wl0gpio3 = (value & 0xFF00) >> 8; - - /* maxpower */ - value = sprom[BCM43xx_SPROM_MAXPWR]; - bcm->sprom.maxpower_aphy = (value & 0xFF00) >> 8; - bcm->sprom.maxpower_bgphy = value & 0x00FF; - - /* pa1b* */ - value = sprom[BCM43xx_SPROM_PA1B0]; - bcm->sprom.pa1b0 = value; - value = sprom[BCM43xx_SPROM_PA1B1]; - bcm->sprom.pa1b1 = value; - value = sprom[BCM43xx_SPROM_PA1B2]; - bcm->sprom.pa1b2 = value; - - /* idle tssi target */ - value = sprom[BCM43xx_SPROM_IDL_TSSI_TGT]; - bcm->sprom.idle_tssi_tgt_aphy = value & 0x00FF; - bcm->sprom.idle_tssi_tgt_bgphy = (value & 0xFF00) >> 8; - - /* boardflags */ - value = sprom[BCM43xx_SPROM_BOARDFLAGS]; - if (value == 0xFFFF) - value = 0x0000; - bcm->sprom.boardflags = value; - /* boardflags workarounds */ - if (bcm->board_vendor == PCI_VENDOR_ID_DELL && - bcm->chip_id == 0x4301 && - bcm->board_revision == 0x74) - bcm->sprom.boardflags |= BCM43xx_BFL_BTCOEXIST; - if (bcm->board_vendor == PCI_VENDOR_ID_APPLE && - bcm->board_type == 0x4E && - bcm->board_revision > 0x40) - bcm->sprom.boardflags |= BCM43xx_BFL_PACTRL; - - /* antenna gain */ - value = sprom[BCM43xx_SPROM_ANTENNA_GAIN]; - if (value == 0x0000 || value == 0xFFFF) - value = 0x0202; - /* convert values to Q5.2 */ - bcm->sprom.antennagain_aphy = ((value & 0xFF00) >> 8) * 4; - bcm->sprom.antennagain_bgphy = (value & 0x00FF) * 4; - - kfree(sprom); - - return 0; -} - -static int bcm43xx_geo_init(struct bcm43xx_private *bcm) -{ - struct ieee80211_geo *geo; - struct ieee80211_channel *chan; - int have_a = 0, have_bg = 0; - int i; - u8 channel; - struct bcm43xx_phyinfo *phy; - const char *iso_country; - u8 max_bg_channel; - - geo = kzalloc(sizeof(*geo), GFP_KERNEL); - if (!geo) - return -ENOMEM; - - for (i = 0; i < bcm->nr_80211_available; i++) { - phy = &(bcm->core_80211_ext[i].phy); - switch (phy->type) { - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - have_bg = 1; - break; - case BCM43xx_PHYTYPE_A: - have_a = 1; - break; - default: - assert(0); - } - } - iso_country = bcm43xx_locale_iso(bcm->sprom.locale); - -/* set the maximum channel based on locale set in sprom or witle locale option */ - switch (bcm->sprom.locale) { - case BCM43xx_LOCALE_THAILAND: - case BCM43xx_LOCALE_ISRAEL: - case BCM43xx_LOCALE_JORDAN: - case BCM43xx_LOCALE_USA_CANADA_ANZ: - case BCM43xx_LOCALE_USA_LOW: - max_bg_channel = 11; - break; - case BCM43xx_LOCALE_JAPAN: - case BCM43xx_LOCALE_JAPAN_HIGH: - max_bg_channel = 14; - break; - default: - max_bg_channel = 13; - } - - if (have_a) { - for (i = 0, channel = IEEE80211_52GHZ_MIN_CHANNEL; - channel <= IEEE80211_52GHZ_MAX_CHANNEL; channel++) { - chan = &geo->a[i++]; - chan->freq = bcm43xx_channel_to_freq_a(channel); - chan->channel = channel; - } - geo->a_channels = i; - } - if (have_bg) { - for (i = 0, channel = IEEE80211_24GHZ_MIN_CHANNEL; - channel <= max_bg_channel; channel++) { - chan = &geo->bg[i++]; - chan->freq = bcm43xx_channel_to_freq_bg(channel); - chan->channel = channel; - } - geo->bg_channels = i; - } - memcpy(geo->name, iso_country, 2); - if (0 /*TODO: Outdoor use only */) - geo->name[2] = 'O'; - else if (0 /*TODO: Indoor use only */) - geo->name[2] = 'I'; - else - geo->name[2] = ' '; - geo->name[3] = '\0'; - - ieee80211_set_geo(bcm->ieee, geo); - kfree(geo); - - return 0; -} - -/* DummyTransmission function, as documented on - * http://bcm-specs.sipsolutions.net/DummyTransmission - */ -void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - unsigned int i, max_loop; - u16 value = 0; - u32 buffer[5] = { - 0x00000000, - 0x0000D400, - 0x00000000, - 0x00000001, - 0x00000000, - }; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - max_loop = 0x1E; - buffer[0] = 0xCC010200; - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - max_loop = 0xFA; - buffer[0] = 0x6E840B00; - break; - default: - assert(0); - return; - } - - for (i = 0; i < 5; i++) - bcm43xx_ram_write(bcm, i * 4, buffer[i]); - - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ - - bcm43xx_write16(bcm, 0x0568, 0x0000); - bcm43xx_write16(bcm, 0x07C0, 0x0000); - bcm43xx_write16(bcm, 0x050C, ((phy->type == BCM43xx_PHYTYPE_A) ? 1 : 0)); - bcm43xx_write16(bcm, 0x0508, 0x0000); - bcm43xx_write16(bcm, 0x050A, 0x0000); - bcm43xx_write16(bcm, 0x054C, 0x0000); - bcm43xx_write16(bcm, 0x056A, 0x0014); - bcm43xx_write16(bcm, 0x0568, 0x0826); - bcm43xx_write16(bcm, 0x0500, 0x0000); - bcm43xx_write16(bcm, 0x0502, 0x0030); - - if (radio->version == 0x2050 && radio->revision <= 0x5) - bcm43xx_radio_write16(bcm, 0x0051, 0x0017); - for (i = 0x00; i < max_loop; i++) { - value = bcm43xx_read16(bcm, 0x050E); - if (value & 0x0080) - break; - udelay(10); - } - for (i = 0x00; i < 0x0A; i++) { - value = bcm43xx_read16(bcm, 0x050E); - if (value & 0x0400) - break; - udelay(10); - } - for (i = 0x00; i < 0x0A; i++) { - value = bcm43xx_read16(bcm, 0x0690); - if (!(value & 0x0100)) - break; - udelay(10); - } - if (radio->version == 0x2050 && radio->revision <= 0x5) - bcm43xx_radio_write16(bcm, 0x0051, 0x0037); -} - -static void key_write(struct bcm43xx_private *bcm, - u8 index, u8 algorithm, const __le16 *key) -{ - unsigned int i, basic_wep = 0; - u32 offset; - u16 value; - - /* Write associated key information */ - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x100 + (index * 2), - ((index << 4) | (algorithm & 0x0F))); - - /* The first 4 WEP keys need extra love */ - if (((algorithm == BCM43xx_SEC_ALGO_WEP) || - (algorithm == BCM43xx_SEC_ALGO_WEP104)) && (index < 4)) - basic_wep = 1; - - /* Write key payload, 8 little endian words */ - offset = bcm->security_offset + (index * BCM43xx_SEC_KEYSIZE); - for (i = 0; i < (BCM43xx_SEC_KEYSIZE / sizeof(u16)); i++) { - value = le16_to_cpu(key[i]); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, - offset + (i * 2), value); - - if (!basic_wep) - continue; - - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, - offset + (i * 2) + 4 * BCM43xx_SEC_KEYSIZE, - value); - } -} - -static void keymac_write(struct bcm43xx_private *bcm, - u8 index, const __be32 *addr) -{ - /* for keys 0-3 there is no associated mac address */ - if (index < 4) - return; - - index -= 4; - if (bcm->current_core->rev >= 5) { - bcm43xx_shm_write32(bcm, - BCM43xx_SHM_HWMAC, - index * 2, - be32_to_cpu(*addr)); - bcm43xx_shm_write16(bcm, - BCM43xx_SHM_HWMAC, - (index * 2) + 1, - be16_to_cpu(*((__be16 *)(addr + 1)))); - } else { - if (index < 8) { - TODO(); /* Put them in the macaddress filter */ - } else { - TODO(); - /* Put them BCM43xx_SHM_SHARED, stating index 0x0120. - Keep in mind to update the count of keymacs in 0x003E as well! */ - } - } -} - -static int bcm43xx_key_write(struct bcm43xx_private *bcm, - u8 index, u8 algorithm, - const u8 *_key, int key_len, - const u8 *mac_addr) -{ - u8 key[BCM43xx_SEC_KEYSIZE] = { 0 }; - - if (index >= ARRAY_SIZE(bcm->key)) - return -EINVAL; - if (key_len > ARRAY_SIZE(key)) - return -EINVAL; - if (algorithm < 1 || algorithm > 5) - return -EINVAL; - - memcpy(key, _key, key_len); - key_write(bcm, index, algorithm, (const __le16 *)key); - keymac_write(bcm, index, (const __be32 *)mac_addr); - - bcm->key[index].algorithm = algorithm; - - return 0; -} - -static void bcm43xx_clear_keys(struct bcm43xx_private *bcm) -{ - static const __be32 zero_mac[2] = { 0 }; - unsigned int i,j, nr_keys = 54; - u16 offset; - - if (bcm->current_core->rev < 5) - nr_keys = 16; - assert(nr_keys <= ARRAY_SIZE(bcm->key)); - - for (i = 0; i < nr_keys; i++) { - bcm->key[i].enabled = 0; - /* returns for i < 4 immediately */ - keymac_write(bcm, i, zero_mac); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, - 0x100 + (i * 2), 0x0000); - for (j = 0; j < 8; j++) { - offset = bcm->security_offset + (j * 4) + (i * BCM43xx_SEC_KEYSIZE); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, - offset, 0x0000); - } - } - dprintk(KERN_INFO PFX "Keys cleared\n"); -} - -/* Lowlevel core-switch function. This is only to be used in - * bcm43xx_switch_core() and bcm43xx_probe_cores() - */ -static int _switch_core(struct bcm43xx_private *bcm, int core) -{ - int err; - int attempts = 0; - u32 current_core; - - assert(core >= 0); - while (1) { - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE, - (core * 0x1000) + 0x18000000); - if (unlikely(err)) - goto error; - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ACTIVE_CORE, - ¤t_core); - if (unlikely(err)) - goto error; - current_core = (current_core - 0x18000000) / 0x1000; - if (current_core == core) - break; - - if (unlikely(attempts++ > BCM43xx_SWITCH_CORE_MAX_RETRIES)) - goto error; - udelay(10); - } - - return 0; -error: - printk(KERN_ERR PFX "Failed to switch to core %d\n", core); - return -ENODEV; -} - -int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core) -{ - int err; - - if (unlikely(!new_core)) - return 0; - if (!new_core->available) - return -ENODEV; - if (bcm->current_core == new_core) - return 0; - err = _switch_core(bcm, new_core->index); - if (unlikely(err)) - goto out; - - bcm->current_core = new_core; -out: - return err; -} - -static int bcm43xx_core_enabled(struct bcm43xx_private *bcm) -{ - u32 value; - - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - value &= BCM43xx_SBTMSTATELOW_CLOCK | BCM43xx_SBTMSTATELOW_RESET - | BCM43xx_SBTMSTATELOW_REJECT; - - return (value == BCM43xx_SBTMSTATELOW_CLOCK); -} - -/* disable current core */ -static int bcm43xx_core_disable(struct bcm43xx_private *bcm, u32 core_flags) -{ - u32 sbtmstatelow; - u32 sbtmstatehigh; - int i; - - /* fetch sbtmstatelow from core information registers */ - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - - /* core is already in reset */ - if (sbtmstatelow & BCM43xx_SBTMSTATELOW_RESET) - goto out; - - if (sbtmstatelow & BCM43xx_SBTMSTATELOW_CLOCK) { - sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | - BCM43xx_SBTMSTATELOW_REJECT; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - - for (i = 0; i < 1000; i++) { - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - if (sbtmstatelow & BCM43xx_SBTMSTATELOW_REJECT) { - i = -1; - break; - } - udelay(10); - } - if (i != -1) { - printk(KERN_ERR PFX "Error: core_disable() REJECT timeout!\n"); - return -EBUSY; - } - - for (i = 0; i < 1000; i++) { - sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (!(sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_BUSY)) { - i = -1; - break; - } - udelay(10); - } - if (i != -1) { - printk(KERN_ERR PFX "Error: core_disable() BUSY timeout!\n"); - return -EBUSY; - } - - sbtmstatelow = BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | - BCM43xx_SBTMSTATELOW_REJECT | - BCM43xx_SBTMSTATELOW_RESET | - BCM43xx_SBTMSTATELOW_CLOCK | - core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(10); - } - - sbtmstatelow = BCM43xx_SBTMSTATELOW_RESET | - BCM43xx_SBTMSTATELOW_REJECT | - core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - -out: - bcm->current_core->enabled = 0; - - return 0; -} - -/* enable (reset) current core */ -static int bcm43xx_core_enable(struct bcm43xx_private *bcm, u32 core_flags) -{ - u32 sbtmstatelow; - u32 sbtmstatehigh; - u32 sbimstate; - int err; - - err = bcm43xx_core_disable(bcm, core_flags); - if (err) - goto out; - - sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | - BCM43xx_SBTMSTATELOW_RESET | - BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | - core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); - - sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (sbtmstatehigh & BCM43xx_SBTMSTATEHIGH_SERROR) { - sbtmstatehigh = 0x00000000; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATEHIGH, sbtmstatehigh); - } - - sbimstate = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMSTATE); - if (sbimstate & (BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT)) { - sbimstate &= ~(BCM43xx_SBIMSTATE_IB_ERROR | BCM43xx_SBIMSTATE_TIMEOUT); - bcm43xx_write32(bcm, BCM43xx_CIR_SBIMSTATE, sbimstate); - } - - sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | - BCM43xx_SBTMSTATELOW_FORCE_GATE_CLOCK | - core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); - - sbtmstatelow = BCM43xx_SBTMSTATELOW_CLOCK | core_flags; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); - - bcm->current_core->enabled = 1; - assert(err == 0); -out: - return err; -} - -/* http://bcm-specs.sipsolutions.net/80211CoreReset */ -void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy) -{ - u32 flags = 0x00040000; - - if ((bcm43xx_core_enabled(bcm)) && - !bcm43xx_using_pio(bcm)) { - } - if (bcm43xx_status(bcm) == BCM43xx_STAT_SHUTTINGDOWN) { - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - & ~(BCM43xx_SBF_MAC_ENABLED | 0x00000002)); - } else { - if (connect_phy) - flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE; - bcm43xx_phy_connect(bcm, connect_phy); - bcm43xx_core_enable(bcm, flags); - bcm43xx_write16(bcm, 0x03E6, 0x0000); - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - | BCM43xx_SBF_400); - } -} - -static void bcm43xx_wireless_core_disable(struct bcm43xx_private *bcm) -{ - bcm43xx_radio_turn_off(bcm); - bcm43xx_write16(bcm, 0x03E6, 0x00F4); - bcm43xx_core_disable(bcm, 0); -} - -/* Mark the current 80211 core inactive. */ -static void bcm43xx_wireless_core_mark_inactive(struct bcm43xx_private *bcm) -{ - u32 sbtmstatelow; - - bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_radio_turn_off(bcm); - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - sbtmstatelow &= 0xDFF5FFFF; - sbtmstatelow |= 0x000A0000; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - sbtmstatelow &= 0xFFF5FFFF; - sbtmstatelow |= 0x00080000; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - udelay(1); -} - -static void handle_irq_transmit_status(struct bcm43xx_private *bcm) -{ - u32 v0, v1; - u16 tmp; - struct bcm43xx_xmitstatus stat; - - while (1) { - v0 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); - if (!v0) - break; - v1 = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1); - - stat.cookie = (v0 >> 16) & 0x0000FFFF; - tmp = (u16)((v0 & 0xFFF0) | ((v0 & 0xF) >> 1)); - stat.flags = tmp & 0xFF; - stat.cnt1 = (tmp & 0x0F00) >> 8; - stat.cnt2 = (tmp & 0xF000) >> 12; - stat.seq = (u16)(v1 & 0xFFFF); - stat.unknown = (u16)((v1 >> 16) & 0xFF); - - bcm43xx_debugfs_log_txstat(bcm, &stat); - - if (stat.flags & BCM43xx_TXSTAT_FLAG_AMPDU) - continue; - if (stat.flags & BCM43xx_TXSTAT_FLAG_INTER) - continue; - - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_handle_xmitstatus(bcm, &stat); - else - bcm43xx_dma_handle_xmitstatus(bcm, &stat); - } -} - -static void drain_txstatus_queue(struct bcm43xx_private *bcm) -{ - u32 dummy; - - if (bcm->current_core->rev < 5) - return; - /* Read all entries from the microcode TXstatus FIFO - * and throw them away. - */ - while (1) { - dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_0); - if (!dummy) - break; - dummy = bcm43xx_read32(bcm, BCM43xx_MMIO_XMITSTAT_1); - } -} - -static void bcm43xx_generate_noise_sample(struct bcm43xx_private *bcm) -{ - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x408, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x40A, 0x7F7F); - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) | (1 << 4)); - assert(bcm->noisecalc.core_at_start == bcm->current_core); - assert(bcm->noisecalc.channel_at_start == bcm43xx_current_radio(bcm)->channel); -} - -static void bcm43xx_calculate_link_quality(struct bcm43xx_private *bcm) -{ - /* Top half of Link Quality calculation. */ - - if (bcm->noisecalc.calculation_running) - return; - bcm->noisecalc.core_at_start = bcm->current_core; - bcm->noisecalc.channel_at_start = bcm43xx_current_radio(bcm)->channel; - bcm->noisecalc.calculation_running = 1; - bcm->noisecalc.nr_samples = 0; - - bcm43xx_generate_noise_sample(bcm); -} - -static void handle_irq_noise(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 tmp; - u8 noise[4]; - u8 i, j; - s32 average; - - /* Bottom half of Link Quality calculation. */ - - assert(bcm->noisecalc.calculation_running); - if (bcm->noisecalc.core_at_start != bcm->current_core || - bcm->noisecalc.channel_at_start != radio->channel) - goto drop_calculation; - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x408); - noise[0] = (tmp & 0x00FF); - noise[1] = (tmp & 0xFF00) >> 8; - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40A); - noise[2] = (tmp & 0x00FF); - noise[3] = (tmp & 0xFF00) >> 8; - if (noise[0] == 0x7F || noise[1] == 0x7F || - noise[2] == 0x7F || noise[3] == 0x7F) - goto generate_new; - - /* Get the noise samples. */ - assert(bcm->noisecalc.nr_samples < 8); - i = bcm->noisecalc.nr_samples; - noise[0] = limit_value(noise[0], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); - noise[1] = limit_value(noise[1], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); - noise[2] = limit_value(noise[2], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); - noise[3] = limit_value(noise[3], 0, ARRAY_SIZE(radio->nrssi_lt) - 1); - bcm->noisecalc.samples[i][0] = radio->nrssi_lt[noise[0]]; - bcm->noisecalc.samples[i][1] = radio->nrssi_lt[noise[1]]; - bcm->noisecalc.samples[i][2] = radio->nrssi_lt[noise[2]]; - bcm->noisecalc.samples[i][3] = radio->nrssi_lt[noise[3]]; - bcm->noisecalc.nr_samples++; - if (bcm->noisecalc.nr_samples == 8) { - /* Calculate the Link Quality by the noise samples. */ - average = 0; - for (i = 0; i < 8; i++) { - for (j = 0; j < 4; j++) - average += bcm->noisecalc.samples[i][j]; - } - average /= (8 * 4); - average *= 125; - average += 64; - average /= 128; - - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x40C); - tmp = (tmp / 128) & 0x1F; - if (tmp >= 8) - average += 2; - else - average -= 25; - if (tmp == 8) - average -= 72; - else - average -= 48; - - bcm->stats.noise = average; -drop_calculation: - bcm->noisecalc.calculation_running = 0; - return; - } -generate_new: - bcm43xx_generate_noise_sample(bcm); -} - -static void handle_irq_ps(struct bcm43xx_private *bcm) -{ - if (bcm->ieee->iw_mode == IW_MODE_MASTER) { - ///TODO: PS TBTT - } else { - if (1/*FIXME: the last PSpoll frame was sent successfully */) - bcm43xx_power_saving_ctl_bits(bcm, -1, -1); - } - if (bcm->ieee->iw_mode == IW_MODE_ADHOC) - bcm->reg124_set_0x4 = 1; - //FIXME else set to false? -} - -static void handle_irq_reg124(struct bcm43xx_private *bcm) -{ - if (!bcm->reg124_set_0x4) - return; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD) - | 0x4); - //FIXME: reset reg124_set_0x4 to false? -} - -static void handle_irq_pmq(struct bcm43xx_private *bcm) -{ - u32 tmp; - - //TODO: AP mode. - - while (1) { - tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_PS_STATUS); - if (!(tmp & 0x00000008)) - break; - } - /* 16bit write is odd, but correct. */ - bcm43xx_write16(bcm, BCM43xx_MMIO_PS_STATUS, 0x0002); -} - -static void bcm43xx_generate_beacon_template(struct bcm43xx_private *bcm, - u16 ram_offset, u16 shm_size_offset) -{ - u32 value; - u16 size = 0; - - /* Timestamp. */ - //FIXME: assumption: The chip sets the timestamp - value = 0; - bcm43xx_ram_write(bcm, ram_offset++, value); - bcm43xx_ram_write(bcm, ram_offset++, value); - size += 8; - - /* Beacon Interval / Capability Information */ - value = 0x0000;//FIXME: Which interval? - value |= (1 << 0) << 16; /* ESS */ - value |= (1 << 2) << 16; /* CF Pollable */ //FIXME? - value |= (1 << 3) << 16; /* CF Poll Request */ //FIXME? - if (!bcm->ieee->open_wep) - value |= (1 << 4) << 16; /* Privacy */ - bcm43xx_ram_write(bcm, ram_offset++, value); - size += 4; - - /* SSID */ - //TODO - - /* FH Parameter Set */ - //TODO - - /* DS Parameter Set */ - //TODO - - /* CF Parameter Set */ - //TODO - - /* TIM */ - //TODO - - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, shm_size_offset, size); -} - -static void handle_irq_beacon(struct bcm43xx_private *bcm) -{ - u32 status; - - bcm->irq_savedstate &= ~BCM43xx_IRQ_BEACON; - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD); - - if ((status & 0x1) && (status & 0x2)) { - /* ACK beacon IRQ. */ - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, - BCM43xx_IRQ_BEACON); - bcm->irq_savedstate |= BCM43xx_IRQ_BEACON; - return; - } - if (!(status & 0x1)) { - bcm43xx_generate_beacon_template(bcm, 0x68, 0x18); - status |= 0x1; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); - } - if (!(status & 0x2)) { - bcm43xx_generate_beacon_template(bcm, 0x468, 0x1A); - status |= 0x2; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS2_BITFIELD, status); - } -} - -/* Interrupt handler bottom-half */ -static void bcm43xx_interrupt_tasklet(struct bcm43xx_private *bcm) -{ - u32 reason; - u32 dma_reason[6]; - u32 merged_dma_reason = 0; - int i, activity = 0; - unsigned long flags; - -#ifdef CONFIG_BCM43XX_DEBUG - u32 _handled = 0x00000000; -# define bcmirq_handled(irq) do { _handled |= (irq); } while (0) -#else -# define bcmirq_handled(irq) do { /* nothing */ } while (0) -#endif /* CONFIG_BCM43XX_DEBUG*/ - - spin_lock_irqsave(&bcm->irq_lock, flags); - reason = bcm->irq_reason; - for (i = 5; i >= 0; i--) { - dma_reason[i] = bcm->dma_reason[i]; - merged_dma_reason |= dma_reason[i]; - } - - if (unlikely(reason & BCM43xx_IRQ_XMIT_ERROR)) { - /* TX error. We get this when Template Ram is written in wrong endianess - * in dummy_tx(). We also get this if something is wrong with the TX header - * on DMA or PIO queues. - * Maybe we get this in other error conditions, too. - */ - printkl(KERN_ERR PFX "FATAL ERROR: BCM43xx_IRQ_XMIT_ERROR\n"); - bcmirq_handled(BCM43xx_IRQ_XMIT_ERROR); - } - if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_FATALMASK)) { - printkl(KERN_ERR PFX "FATAL ERROR: Fatal DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - bcm43xx_controller_restart(bcm, "DMA error"); - mmiowb(); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - return; - } - if (unlikely(merged_dma_reason & BCM43xx_DMAIRQ_NONFATALMASK)) { - printkl(KERN_ERR PFX "DMA error: " - "0x%08X, 0x%08X, 0x%08X, " - "0x%08X, 0x%08X, 0x%08X\n", - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3], - dma_reason[4], dma_reason[5]); - } - - if (reason & BCM43xx_IRQ_PS) { - handle_irq_ps(bcm); - bcmirq_handled(BCM43xx_IRQ_PS); - } - - if (reason & BCM43xx_IRQ_REG124) { - handle_irq_reg124(bcm); - bcmirq_handled(BCM43xx_IRQ_REG124); - } - - if (reason & BCM43xx_IRQ_BEACON) { - if (bcm->ieee->iw_mode == IW_MODE_MASTER) - handle_irq_beacon(bcm); - bcmirq_handled(BCM43xx_IRQ_BEACON); - } - - if (reason & BCM43xx_IRQ_PMQ) { - handle_irq_pmq(bcm); - bcmirq_handled(BCM43xx_IRQ_PMQ); - } - - if (reason & BCM43xx_IRQ_SCAN) { - /*TODO*/ - //bcmirq_handled(BCM43xx_IRQ_SCAN); - } - - if (reason & BCM43xx_IRQ_NOISE) { - handle_irq_noise(bcm); - bcmirq_handled(BCM43xx_IRQ_NOISE); - } - - /* Check the DMA reason registers for received data. */ - if (dma_reason[0] & BCM43xx_DMAIRQ_RX_DONE) { - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue0); - else - bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring0); - /* We intentionally don't set "activity" to 1, here. */ - } - assert(!(dma_reason[1] & BCM43xx_DMAIRQ_RX_DONE)); - assert(!(dma_reason[2] & BCM43xx_DMAIRQ_RX_DONE)); - if (dma_reason[3] & BCM43xx_DMAIRQ_RX_DONE) { - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_rx(bcm43xx_current_pio(bcm)->queue3); - else - bcm43xx_dma_rx(bcm43xx_current_dma(bcm)->rx_ring3); - activity = 1; - } - assert(!(dma_reason[4] & BCM43xx_DMAIRQ_RX_DONE)); - assert(!(dma_reason[5] & BCM43xx_DMAIRQ_RX_DONE)); - bcmirq_handled(BCM43xx_IRQ_RX); - - if (reason & BCM43xx_IRQ_XMIT_STATUS) { - handle_irq_transmit_status(bcm); - activity = 1; - //TODO: In AP mode, this also causes sending of powersave responses. - bcmirq_handled(BCM43xx_IRQ_XMIT_STATUS); - } - - /* IRQ_PIO_WORKAROUND is handled in the top-half. */ - bcmirq_handled(BCM43xx_IRQ_PIO_WORKAROUND); -#ifdef CONFIG_BCM43XX_DEBUG - if (unlikely(reason & ~_handled)) { - printkl(KERN_WARNING PFX - "Unhandled IRQ! Reason: 0x%08x, Unhandled: 0x%08x, " - "DMA: 0x%08x, 0x%08x, 0x%08x, 0x%08x\n", - reason, (reason & ~_handled), - dma_reason[0], dma_reason[1], - dma_reason[2], dma_reason[3]); - } -#endif -#undef bcmirq_handled - - if (!modparam_noleds) - bcm43xx_leds_update(bcm, activity); - bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - mmiowb(); - spin_unlock_irqrestore(&bcm->irq_lock, flags); -} - -static void pio_irq_workaround(struct bcm43xx_private *bcm, - u16 base, int queueidx) -{ - u16 rxctl; - - rxctl = bcm43xx_read16(bcm, base + BCM43xx_PIO_RXCTL); - if (rxctl & BCM43xx_PIO_RXCTL_DATAAVAILABLE) - bcm->dma_reason[queueidx] |= BCM43xx_DMAIRQ_RX_DONE; - else - bcm->dma_reason[queueidx] &= ~BCM43xx_DMAIRQ_RX_DONE; -} - -static void bcm43xx_interrupt_ack(struct bcm43xx_private *bcm, u32 reason) -{ - if (bcm43xx_using_pio(bcm) && - (bcm->current_core->rev < 3) && - (!(reason & BCM43xx_IRQ_PIO_WORKAROUND))) { - /* Apply a PIO specific workaround to the dma_reasons */ - pio_irq_workaround(bcm, BCM43xx_MMIO_PIO1_BASE, 0); - pio_irq_workaround(bcm, BCM43xx_MMIO_PIO2_BASE, 1); - pio_irq_workaround(bcm, BCM43xx_MMIO_PIO3_BASE, 2); - pio_irq_workaround(bcm, BCM43xx_MMIO_PIO4_BASE, 3); - } - - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, reason); - - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_REASON, - bcm->dma_reason[0]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_REASON, - bcm->dma_reason[1]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_REASON, - bcm->dma_reason[2]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_REASON, - bcm->dma_reason[3]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_REASON, - bcm->dma_reason[4]); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_REASON, - bcm->dma_reason[5]); -} - -/* Interrupt handler top-half */ -static irqreturn_t bcm43xx_interrupt_handler(int irq, void *dev_id) -{ - irqreturn_t ret = IRQ_HANDLED; - struct bcm43xx_private *bcm = dev_id; - u32 reason; - - if (!bcm) - return IRQ_NONE; - - spin_lock(&bcm->irq_lock); - - reason = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (reason == 0xffffffff) { - /* irq not for us (shared irq) */ - ret = IRQ_NONE; - goto out; - } - reason &= bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_MASK); - if (!reason) - goto out; - - assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - assert(bcm->current_core->id == BCM43xx_COREID_80211); - - bcm->dma_reason[0] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA0_REASON) - & 0x0001DC00; - bcm->dma_reason[1] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA1_REASON) - & 0x0000DC00; - bcm->dma_reason[2] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA2_REASON) - & 0x0000DC00; - bcm->dma_reason[3] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA3_REASON) - & 0x0001DC00; - bcm->dma_reason[4] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA4_REASON) - & 0x0000DC00; - bcm->dma_reason[5] = bcm43xx_read32(bcm, BCM43xx_MMIO_DMA5_REASON) - & 0x0000DC00; - - bcm43xx_interrupt_ack(bcm, reason); - - /* disable all IRQs. They are enabled again in the bottom half. */ - bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - /* save the reason code and call our bottom half. */ - bcm->irq_reason = reason; - tasklet_schedule(&bcm->isr_tasklet); - -out: - mmiowb(); - spin_unlock(&bcm->irq_lock); - - return ret; -} - -static void bcm43xx_release_firmware(struct bcm43xx_private *bcm, int force) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (bcm->firmware_norelease && !force) - return; /* Suspending or controller reset. */ - release_firmware(phy->ucode); - phy->ucode = NULL; - release_firmware(phy->pcm); - phy->pcm = NULL; - release_firmware(phy->initvals0); - phy->initvals0 = NULL; - release_firmware(phy->initvals1); - phy->initvals1 = NULL; -} - -static int bcm43xx_request_firmware(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u8 rev = bcm->current_core->rev; - int err = 0; - int nr; - char buf[22 + sizeof(modparam_fwpostfix) - 1] = { 0 }; - - if (!phy->ucode) { - snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_microcode%d%s.fw", - (rev >= 5 ? 5 : rev), - modparam_fwpostfix); - err = request_firmware(&phy->ucode, buf, &bcm->pci_dev->dev); - if (err) { - printk(KERN_ERR PFX - "Error: Microcode \"%s\" not available or load failed.\n", - buf); - goto error; - } - } - - if (!phy->pcm) { - snprintf(buf, ARRAY_SIZE(buf), - "bcm43xx_pcm%d%s.fw", - (rev < 5 ? 4 : 5), - modparam_fwpostfix); - err = request_firmware(&phy->pcm, buf, &bcm->pci_dev->dev); - if (err) { - printk(KERN_ERR PFX - "Error: PCM \"%s\" not available or load failed.\n", - buf); - goto error; - } - } - - if (!phy->initvals0) { - if (rev == 2 || rev == 4) { - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - nr = 3; - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - nr = 1; - break; - default: - goto err_noinitval; - } - - } else if (rev >= 5) { - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - nr = 7; - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - nr = 5; - break; - default: - goto err_noinitval; - } - } else - goto err_noinitval; - snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", - nr, modparam_fwpostfix); - - err = request_firmware(&phy->initvals0, buf, &bcm->pci_dev->dev); - if (err) { - printk(KERN_ERR PFX - "Error: InitVals \"%s\" not available or load failed.\n", - buf); - goto error; - } - if (phy->initvals0->size % sizeof(struct bcm43xx_initval)) { - printk(KERN_ERR PFX "InitVals fileformat error.\n"); - goto error; - } - } - - if (!phy->initvals1) { - if (rev >= 5) { - u32 sbtmstatehigh; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - sbtmstatehigh = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (sbtmstatehigh & 0x00010000) - nr = 9; - else - nr = 10; - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - nr = 6; - break; - default: - goto err_noinitval; - } - snprintf(buf, ARRAY_SIZE(buf), "bcm43xx_initval%02d%s.fw", - nr, modparam_fwpostfix); - - err = request_firmware(&phy->initvals1, buf, &bcm->pci_dev->dev); - if (err) { - printk(KERN_ERR PFX - "Error: InitVals \"%s\" not available or load failed.\n", - buf); - goto error; - } - if (phy->initvals1->size % sizeof(struct bcm43xx_initval)) { - printk(KERN_ERR PFX "InitVals fileformat error.\n"); - goto error; - } - } - } - -out: - return err; -error: - bcm43xx_release_firmware(bcm, 1); - goto out; -err_noinitval: - printk(KERN_ERR PFX "Error: No InitVals available!\n"); - err = -ENOENT; - goto error; -} - -static void bcm43xx_upload_microcode(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - const __be32 *data; - unsigned int i, len; - - /* Upload Microcode. */ - data = (__be32 *)(phy->ucode->data); - len = phy->ucode->size / sizeof(u32); - bcm43xx_shm_control_word(bcm, BCM43xx_SHM_UCODE, 0x0000); - for (i = 0; i < len; i++) { - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, - be32_to_cpu(data[i])); - udelay(10); - } - - /* Upload PCM data. */ - data = (__be32 *)(phy->pcm->data); - len = phy->pcm->size / sizeof(u32); - bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01ea); - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, 0x00004000); - bcm43xx_shm_control_word(bcm, BCM43xx_SHM_PCM, 0x01eb); - for (i = 0; i < len; i++) { - bcm43xx_write32(bcm, BCM43xx_MMIO_SHM_DATA, - be32_to_cpu(data[i])); - udelay(10); - } -} - -static int bcm43xx_write_initvals(struct bcm43xx_private *bcm, - const struct bcm43xx_initval *data, - const unsigned int len) -{ - u16 offset, size; - u32 value; - unsigned int i; - - for (i = 0; i < len; i++) { - offset = be16_to_cpu(data[i].offset); - size = be16_to_cpu(data[i].size); - value = be32_to_cpu(data[i].value); - - if (unlikely(offset >= 0x1000)) - goto err_format; - if (size == 2) { - if (unlikely(value & 0xFFFF0000)) - goto err_format; - bcm43xx_write16(bcm, offset, (u16)value); - } else if (size == 4) { - bcm43xx_write32(bcm, offset, value); - } else - goto err_format; - } - - return 0; - -err_format: - printk(KERN_ERR PFX "InitVals (bcm43xx_initvalXX.fw) file-format error. " - "Please fix your bcm43xx firmware files.\n"); - return -EPROTO; -} - -static int bcm43xx_upload_initvals(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - int err; - - err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals0->data, - phy->initvals0->size / sizeof(struct bcm43xx_initval)); - if (err) - goto out; - if (phy->initvals1) { - err = bcm43xx_write_initvals(bcm, (struct bcm43xx_initval *)phy->initvals1->data, - phy->initvals1->size / sizeof(struct bcm43xx_initval)); - if (err) - goto out; - } -out: - return err; -} - -static int bcm43xx_initialize_irq(struct bcm43xx_private *bcm) -{ - int err; - - bcm->irq = bcm->pci_dev->irq; - err = request_irq(bcm->irq, bcm43xx_interrupt_handler, - IRQF_SHARED, KBUILD_MODNAME, bcm); - if (err) - printk(KERN_ERR PFX "Cannot register IRQ%d\n", bcm->irq); - - return err; -} - -/* Switch to the core used to write the GPIO register. - * This is either the ChipCommon, or the PCI core. - */ -static int switch_to_gpio_core(struct bcm43xx_private *bcm) -{ - int err; - - /* Where to find the GPIO register depends on the chipset. - * If it has a ChipCommon, its register at offset 0x6c is the GPIO - * control register. Otherwise the register at offset 0x6c in the - * PCI core is the GPIO control register. - */ - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err == -ENODEV) { - err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (unlikely(err == -ENODEV)) { - printk(KERN_ERR PFX "gpio error: " - "Neither ChipCommon nor PCI core available!\n"); - } - } - - return err; -} - -/* Initialize the GPIOs - * http://bcm-specs.sipsolutions.net/GPIO - */ -static int bcm43xx_gpio_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_coreinfo *old_core; - int err; - u32 mask, set; - - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - & 0xFFFF3FFF); - - bcm43xx_leds_switch_all(bcm, 0); - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, - bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) | 0x000F); - - mask = 0x0000001F; - set = 0x0000000F; - if (bcm->chip_id == 0x4301) { - mask |= 0x0060; - set |= 0x0060; - } - if (0 /* FIXME: conditional unknown */) { - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, - bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) - | 0x0100); - mask |= 0x0180; - set |= 0x0180; - } - if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { - bcm43xx_write16(bcm, BCM43xx_MMIO_GPIO_MASK, - bcm43xx_read16(bcm, BCM43xx_MMIO_GPIO_MASK) - | 0x0200); - mask |= 0x0200; - set |= 0x0200; - } - if (bcm->current_core->rev >= 2) - mask |= 0x0010; /* FIXME: This is redundant. */ - - old_core = bcm->current_core; - err = switch_to_gpio_core(bcm); - if (err) - goto out; - bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, - (bcm43xx_read32(bcm, BCM43xx_GPIO_CONTROL) & mask) | set); - err = bcm43xx_switch_core(bcm, old_core); -out: - return err; -} - -/* Turn off all GPIO stuff. Call this on module unload, for example. */ -static int bcm43xx_gpio_cleanup(struct bcm43xx_private *bcm) -{ - struct bcm43xx_coreinfo *old_core; - int err; - - old_core = bcm->current_core; - err = switch_to_gpio_core(bcm); - if (err) - return err; - bcm43xx_write32(bcm, BCM43xx_GPIO_CONTROL, 0x00000000); - err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - - return 0; -} - -/* http://bcm-specs.sipsolutions.net/EnableMac */ -void bcm43xx_mac_enable(struct bcm43xx_private *bcm) -{ - bcm->mac_suspended--; - assert(bcm->mac_suspended >= 0); - if (bcm->mac_suspended == 0) { - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - | BCM43xx_SBF_MAC_ENABLED); - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, BCM43xx_IRQ_READY); - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* dummy read */ - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - bcm43xx_power_saving_ctl_bits(bcm, -1, -1); - } -} - -/* http://bcm-specs.sipsolutions.net/SuspendMAC */ -void bcm43xx_mac_suspend(struct bcm43xx_private *bcm) -{ - int i; - u32 tmp; - - assert(bcm->mac_suspended >= 0); - if (bcm->mac_suspended == 0) { - bcm43xx_power_saving_ctl_bits(bcm, -1, 1); - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) - & ~BCM43xx_SBF_MAC_ENABLED); - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - for (i = 10000; i; i--) { - tmp = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (tmp & BCM43xx_IRQ_READY) - goto out; - udelay(1); - } - printkl(KERN_ERR PFX "MAC suspend failed\n"); - } -out: - bcm->mac_suspended++; -} - -void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, - int iw_mode) -{ - unsigned long flags; - struct net_device *net_dev = bcm->net_dev; - u32 status; - u16 value; - - spin_lock_irqsave(&bcm->ieee->lock, flags); - bcm->ieee->iw_mode = iw_mode; - spin_unlock_irqrestore(&bcm->ieee->lock, flags); - if (iw_mode == IW_MODE_MONITOR) - net_dev->type = ARPHRD_IEEE80211; - else - net_dev->type = ARPHRD_ETHER; - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - /* Reset status to infrastructured mode */ - status &= ~(BCM43xx_SBF_MODE_AP | BCM43xx_SBF_MODE_MONITOR); - status &= ~BCM43xx_SBF_MODE_PROMISC; - status |= BCM43xx_SBF_MODE_NOTADHOC; - -/* FIXME: Always enable promisc mode, until we get the MAC filters working correctly. */ -status |= BCM43xx_SBF_MODE_PROMISC; - - switch (iw_mode) { - case IW_MODE_MONITOR: - status |= BCM43xx_SBF_MODE_MONITOR; - status |= BCM43xx_SBF_MODE_PROMISC; - break; - case IW_MODE_ADHOC: - status &= ~BCM43xx_SBF_MODE_NOTADHOC; - break; - case IW_MODE_MASTER: - status |= BCM43xx_SBF_MODE_AP; - break; - case IW_MODE_SECOND: - case IW_MODE_REPEAT: - TODO(); /* TODO */ - break; - case IW_MODE_INFRA: - /* nothing to be done here... */ - break; - default: - dprintk(KERN_ERR PFX "Unknown mode in set_iwmode: %d\n", iw_mode); - } - if (net_dev->flags & IFF_PROMISC) - status |= BCM43xx_SBF_MODE_PROMISC; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - - value = 0x0002; - if (iw_mode != IW_MODE_ADHOC && iw_mode != IW_MODE_MASTER) { - if (bcm->chip_id == 0x4306 && bcm->chip_rev == 3) - value = 0x0064; - else - value = 0x0032; - } - bcm43xx_write16(bcm, 0x0612, value); -} - -/* This is the opposite of bcm43xx_chip_init() */ -static void bcm43xx_chip_cleanup(struct bcm43xx_private *bcm) -{ - bcm43xx_radio_turn_off(bcm); - if (!modparam_noleds) - bcm43xx_leds_exit(bcm); - bcm43xx_gpio_cleanup(bcm); - bcm43xx_release_firmware(bcm, 0); -} - -/* Initialize the chip - * http://bcm-specs.sipsolutions.net/ChipInit - */ -static int bcm43xx_chip_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - int err; - int i, tmp; - u32 value32; - u16 value16; - - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, - BCM43xx_SBF_CORE_READY - | BCM43xx_SBF_400); - - err = bcm43xx_request_firmware(bcm); - if (err) - goto out; - bcm43xx_upload_microcode(bcm); - - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0xFFFFFFFF); - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, 0x00020402); - i = 0; - while (1) { - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (value32 == BCM43xx_IRQ_READY) - break; - i++; - if (i >= BCM43xx_IRQWAIT_MAX_RETRIES) { - printk(KERN_ERR PFX "IRQ_READY timeout\n"); - err = -ENODEV; - goto err_release_fw; - } - udelay(10); - } - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - - value16 = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_REVISION); - - dprintk(KERN_INFO PFX "Microcode rev 0x%x, pl 0x%x " - "(20%.2i-%.2i-%.2i %.2i:%.2i:%.2i)\n", value16, - bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_PATCHLEVEL), - (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_DATE) >> 12) & 0xf, - (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_DATE) >> 8) & 0xf, - bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_DATE) & 0xff, - (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_TIME) >> 11) & 0x1f, - (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_TIME) >> 5) & 0x3f, - bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_TIME) & 0x1f); - - if ( value16 > 0x128 ) { - printk(KERN_ERR PFX - "Firmware: no support for microcode extracted " - "from version 4.x binary drivers.\n"); - err = -EOPNOTSUPP; - goto err_release_fw; - } - - err = bcm43xx_gpio_init(bcm); - if (err) - goto err_release_fw; - - err = bcm43xx_upload_initvals(bcm); - if (err) - goto err_gpio_cleanup; - bcm43xx_radio_turn_on(bcm); - bcm->radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm); - printk(KERN_INFO PFX "Radio %s by hardware\n", - (bcm->radio_hw_enable == 0) ? "disabled" : "enabled"); - - bcm43xx_write16(bcm, 0x03E6, 0x0000); - err = bcm43xx_phy_init(bcm); - if (err) - goto err_radio_off; - - /* Select initial Interference Mitigation. */ - tmp = radio->interfmode; - radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; - bcm43xx_radio_set_interference_mitigation(bcm, tmp); - - bcm43xx_phy_set_antenna_diversity(bcm); - bcm43xx_radio_set_txantenna(bcm, BCM43xx_RADIO_TXANTENNA_DEFAULT); - if (phy->type == BCM43xx_PHYTYPE_B) { - value16 = bcm43xx_read16(bcm, 0x005E); - value16 |= 0x0004; - bcm43xx_write16(bcm, 0x005E, value16); - } - bcm43xx_write32(bcm, 0x0100, 0x01000000); - if (bcm->current_core->rev < 5) - bcm43xx_write32(bcm, 0x010C, 0x01000000); - - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 &= ~ BCM43xx_SBF_MODE_NOTADHOC; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= BCM43xx_SBF_MODE_NOTADHOC; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - - value32 = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value32 |= 0x100000; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value32); - - if (bcm43xx_using_pio(bcm)) { - bcm43xx_write32(bcm, 0x0210, 0x00000100); - bcm43xx_write32(bcm, 0x0230, 0x00000100); - bcm43xx_write32(bcm, 0x0250, 0x00000100); - bcm43xx_write32(bcm, 0x0270, 0x00000100); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0034, 0x0000); - } - - /* Probe Response Timeout value */ - /* FIXME: Default to 0, has to be set by ioctl probably... :-/ */ - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0074, 0x0000); - - /* Initially set the wireless operation mode. */ - bcm43xx_set_iwmode(bcm, bcm->ieee->iw_mode); - - if (bcm->current_core->rev < 3) { - bcm43xx_write16(bcm, 0x060E, 0x0000); - bcm43xx_write16(bcm, 0x0610, 0x8000); - bcm43xx_write16(bcm, 0x0604, 0x0000); - bcm43xx_write16(bcm, 0x0606, 0x0200); - } else { - bcm43xx_write32(bcm, 0x0188, 0x80000000); - bcm43xx_write32(bcm, 0x018C, 0x02000000); - } - bcm43xx_write32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON, 0x00004000); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA0_IRQ_MASK, 0x0001DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA1_IRQ_MASK, 0x0000DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA2_IRQ_MASK, 0x0000DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA3_IRQ_MASK, 0x0001DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA4_IRQ_MASK, 0x0000DC00); - bcm43xx_write32(bcm, BCM43xx_MMIO_DMA5_IRQ_MASK, 0x0000DC00); - - value32 = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - value32 |= 0x00100000; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, value32); - - bcm43xx_write16(bcm, BCM43xx_MMIO_POWERUP_DELAY, bcm43xx_pctl_powerup_delay(bcm)); - - assert(err == 0); - dprintk(KERN_INFO PFX "Chip initialized\n"); -out: - return err; - -err_radio_off: - bcm43xx_radio_turn_off(bcm); -err_gpio_cleanup: - bcm43xx_gpio_cleanup(bcm); -err_release_fw: - bcm43xx_release_firmware(bcm, 1); - goto out; -} - -/* Validate chip access - * http://bcm-specs.sipsolutions.net/ValidateChipAccess */ -static int bcm43xx_validate_chip(struct bcm43xx_private *bcm) -{ - u32 value; - u32 shm_backup; - - shm_backup = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0xAA5555AA); - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0xAA5555AA) - goto error; - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, 0x55AAAA55); - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0000) != 0x55AAAA55) - goto error; - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, 0x0000, shm_backup); - - value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if ((value | 0x80000000) != 0x80000400) - goto error; - - value = bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); - if (value != 0x00000000) - goto error; - - return 0; -error: - printk(KERN_ERR PFX "Failed to validate the chipaccess\n"); - return -ENODEV; -} - -static void bcm43xx_init_struct_phyinfo(struct bcm43xx_phyinfo *phy) -{ - /* Initialize a "phyinfo" structure. The structure is already - * zeroed out. - * This is called on insmod time to initialize members. - */ - phy->savedpctlreg = 0xFFFF; - spin_lock_init(&phy->lock); -} - -static void bcm43xx_init_struct_radioinfo(struct bcm43xx_radioinfo *radio) -{ - /* Initialize a "radioinfo" structure. The structure is already - * zeroed out. - * This is called on insmod time to initialize members. - */ - radio->interfmode = BCM43xx_RADIO_INTERFMODE_NONE; - radio->channel = 0xFF; - radio->initial_channel = 0xFF; -} - -static int bcm43xx_probe_cores(struct bcm43xx_private *bcm) -{ - int err, i; - int current_core; - u32 core_vendor, core_id, core_rev; - u32 sb_id_hi, chip_id_32 = 0; - u16 pci_device, chip_id_16; - u8 core_count; - - memset(&bcm->core_chipcommon, 0, sizeof(struct bcm43xx_coreinfo)); - memset(&bcm->core_pci, 0, sizeof(struct bcm43xx_coreinfo)); - memset(&bcm->core_80211, 0, sizeof(struct bcm43xx_coreinfo) - * BCM43xx_MAX_80211_CORES); - memset(&bcm->core_80211_ext, 0, sizeof(struct bcm43xx_coreinfo_80211) - * BCM43xx_MAX_80211_CORES); - bcm->nr_80211_available = 0; - bcm->current_core = NULL; - bcm->active_80211_core = NULL; - - /* map core 0 */ - err = _switch_core(bcm, 0); - if (err) - goto out; - - /* fetch sb_id_hi from core information registers */ - sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); - - core_id = (sb_id_hi & 0x8FF0) >> 4; - core_rev = (sb_id_hi & 0x7000) >> 8; - core_rev |= (sb_id_hi & 0xF); - core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; - - /* if present, chipcommon is always core 0; read the chipid from it */ - if (core_id == BCM43xx_COREID_CHIPCOMMON) { - chip_id_32 = bcm43xx_read32(bcm, 0); - chip_id_16 = chip_id_32 & 0xFFFF; - bcm->core_chipcommon.available = 1; - bcm->core_chipcommon.id = core_id; - bcm->core_chipcommon.rev = core_rev; - bcm->core_chipcommon.index = 0; - /* While we are at it, also read the capabilities. */ - bcm->chipcommon_capabilities = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_CAPABILITIES); - } else { - /* without a chipCommon, use a hard coded table. */ - pci_device = bcm->pci_dev->device; - if (pci_device == 0x4301) - chip_id_16 = 0x4301; - else if ((pci_device >= 0x4305) && (pci_device <= 0x4307)) - chip_id_16 = 0x4307; - else if ((pci_device >= 0x4402) && (pci_device <= 0x4403)) - chip_id_16 = 0x4402; - else if ((pci_device >= 0x4610) && (pci_device <= 0x4615)) - chip_id_16 = 0x4610; - else if ((pci_device >= 0x4710) && (pci_device <= 0x4715)) - chip_id_16 = 0x4710; - else { - printk(KERN_ERR PFX "Could not determine Chip ID\n"); - return -ENODEV; - } - } - - /* ChipCommon with Core Rev >=4 encodes number of cores, - * otherwise consult hardcoded table */ - if ((core_id == BCM43xx_COREID_CHIPCOMMON) && (core_rev >= 4)) { - core_count = (chip_id_32 & 0x0F000000) >> 24; - } else { - switch (chip_id_16) { - case 0x4610: - case 0x4704: - case 0x4710: - core_count = 9; - break; - case 0x4310: - core_count = 8; - break; - case 0x5365: - core_count = 7; - break; - case 0x4306: - core_count = 6; - break; - case 0x4301: - case 0x4307: - core_count = 5; - break; - case 0x4402: - core_count = 3; - break; - default: - /* SOL if we get here */ - assert(0); - core_count = 1; - } - } - - bcm->chip_id = chip_id_16; - bcm->chip_rev = (chip_id_32 & 0x000F0000) >> 16; - bcm->chip_package = (chip_id_32 & 0x00F00000) >> 20; - - dprintk(KERN_INFO PFX "Chip ID 0x%x, rev 0x%x\n", - bcm->chip_id, bcm->chip_rev); - dprintk(KERN_INFO PFX "Number of cores: %d\n", core_count); - if (bcm->core_chipcommon.available) { - dprintk(KERN_INFO PFX "Core 0: ID 0x%x, rev 0x%x, vendor 0x%x\n", - core_id, core_rev, core_vendor); - current_core = 1; - } else - current_core = 0; - for ( ; current_core < core_count; current_core++) { - struct bcm43xx_coreinfo *core; - struct bcm43xx_coreinfo_80211 *ext_80211; - - err = _switch_core(bcm, current_core); - if (err) - goto out; - /* Gather information */ - /* fetch sb_id_hi from core information registers */ - sb_id_hi = bcm43xx_read32(bcm, BCM43xx_CIR_SB_ID_HI); - - /* extract core_id, core_rev, core_vendor */ - core_id = (sb_id_hi & 0x8FF0) >> 4; - core_rev = ((sb_id_hi & 0xF) | ((sb_id_hi & 0x7000) >> 8)); - core_vendor = (sb_id_hi & 0xFFFF0000) >> 16; - - dprintk(KERN_INFO PFX "Core %d: ID 0x%x, rev 0x%x, vendor 0x%x\n", - current_core, core_id, core_rev, core_vendor); - - core = NULL; - switch (core_id) { - case BCM43xx_COREID_PCI: - case BCM43xx_COREID_PCIE: - core = &bcm->core_pci; - if (core->available) { - printk(KERN_WARNING PFX "Multiple PCI cores found.\n"); - continue; - } - break; - case BCM43xx_COREID_80211: - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - core = &(bcm->core_80211[i]); - ext_80211 = &(bcm->core_80211_ext[i]); - if (!core->available) - break; - core = NULL; - } - if (!core) { - printk(KERN_WARNING PFX "More than %d cores of type 802.11 found.\n", - BCM43xx_MAX_80211_CORES); - continue; - } - if (i != 0) { - /* More than one 80211 core is only supported - * by special chips. - * There are chips with two 80211 cores, but with - * dangling pins on the second core. Be careful - * and ignore these cores here. - */ - if (1 /*bcm->pci_dev->device != 0x4324*/ ) { - /* TODO: A PHY */ - dprintk(KERN_INFO PFX "Ignoring additional 802.11a core.\n"); - continue; - } - } - switch (core_rev) { - case 2: - case 4: - case 5: - case 6: - case 7: - case 9: - case 10: - break; - default: - printk(KERN_WARNING PFX - "Unsupported 80211 core revision %u\n", - core_rev); - } - bcm->nr_80211_available++; - core->priv = ext_80211; - bcm43xx_init_struct_phyinfo(&ext_80211->phy); - bcm43xx_init_struct_radioinfo(&ext_80211->radio); - break; - case BCM43xx_COREID_CHIPCOMMON: - printk(KERN_WARNING PFX "Multiple CHIPCOMMON cores found.\n"); - break; - } - if (core) { - core->available = 1; - core->id = core_id; - core->rev = core_rev; - core->index = current_core; - } - } - - if (!bcm->core_80211[0].available) { - printk(KERN_ERR PFX "Error: No 80211 core found!\n"); - err = -ENODEV; - goto out; - } - - err = bcm43xx_switch_core(bcm, &bcm->core_80211[0]); - - assert(err == 0); -out: - return err; -} - -static void bcm43xx_gen_bssid(struct bcm43xx_private *bcm) -{ - const u8 *mac = (const u8*)(bcm->net_dev->dev_addr); - u8 *bssid = bcm->ieee->bssid; - - switch (bcm->ieee->iw_mode) { - case IW_MODE_ADHOC: - random_ether_addr(bssid); - break; - case IW_MODE_MASTER: - case IW_MODE_INFRA: - case IW_MODE_REPEAT: - case IW_MODE_SECOND: - case IW_MODE_MONITOR: - memcpy(bssid, mac, ETH_ALEN); - break; - default: - assert(0); - } -} - -static void bcm43xx_rate_memory_write(struct bcm43xx_private *bcm, - u16 rate, - int is_ofdm) -{ - u16 offset; - - if (is_ofdm) { - offset = 0x480; - offset += (bcm43xx_plcp_get_ratecode_ofdm(rate) & 0x000F) * 2; - } - else { - offset = 0x4C0; - offset += (bcm43xx_plcp_get_ratecode_cck(rate) & 0x000F) * 2; - } - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, offset + 0x20, - bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, offset)); -} - -static void bcm43xx_rate_memory_init(struct bcm43xx_private *bcm) -{ - switch (bcm43xx_current_phy(bcm)->type) { - case BCM43xx_PHYTYPE_A: - case BCM43xx_PHYTYPE_G: - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_6MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_12MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_18MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_24MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_36MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_48MB, 1); - bcm43xx_rate_memory_write(bcm, IEEE80211_OFDM_RATE_54MB, 1); - case BCM43xx_PHYTYPE_B: - bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_1MB, 0); - bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_2MB, 0); - bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_5MB, 0); - bcm43xx_rate_memory_write(bcm, IEEE80211_CCK_RATE_11MB, 0); - break; - default: - assert(0); - } -} - -static void bcm43xx_wireless_core_cleanup(struct bcm43xx_private *bcm) -{ - bcm43xx_chip_cleanup(bcm); - bcm43xx_pio_free(bcm); - bcm43xx_dma_free(bcm); - - bcm->current_core->initialized = 0; -} - -/* http://bcm-specs.sipsolutions.net/80211Init */ -static int bcm43xx_wireless_core_init(struct bcm43xx_private *bcm, - int active_wlcore) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u32 ucodeflags; - int err; - u32 sbimconfiglow; - u8 limit; - - if (bcm->core_pci.rev <= 5 && bcm->core_pci.id != BCM43xx_COREID_PCIE) { - sbimconfiglow = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); - sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; - sbimconfiglow &= ~ BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - if (bcm->bustype == BCM43xx_BUSTYPE_PCI) - sbimconfiglow |= 0x32; - else - sbimconfiglow |= 0x53; - bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, sbimconfiglow); - } - - bcm43xx_phy_calibrate(bcm); - err = bcm43xx_chip_init(bcm); - if (err) - goto out; - - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0016, bcm->current_core->rev); - ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, BCM43xx_UCODEFLAGS_OFFSET); - - if (0 /*FIXME: which condition has to be used here? */) - ucodeflags |= 0x00000010; - - /* HW decryption needs to be set now */ - ucodeflags |= 0x40000000; - - if (phy->type == BCM43xx_PHYTYPE_G) { - ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; - if (phy->rev == 1) - ucodeflags |= BCM43xx_UCODEFLAG_UNKGPHY; - if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) - ucodeflags |= BCM43xx_UCODEFLAG_UNKPACTRL; - } else if (phy->type == BCM43xx_PHYTYPE_B) { - ucodeflags |= BCM43xx_UCODEFLAG_UNKBGPHY; - if (phy->rev >= 2 && radio->version == 0x2050) - ucodeflags &= ~BCM43xx_UCODEFLAG_UNKGPHY; - } - - if (ucodeflags != bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET)) { - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, ucodeflags); - } - - /* Short/Long Retry Limit. - * The retry-limit is a 4-bit counter. Enforce this to avoid overflowing - * the chip-internal counter. - */ - limit = limit_value(modparam_short_retry, 0, 0xF); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0006, limit); - limit = limit_value(modparam_long_retry, 0, 0xF); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0007, limit); - - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0044, 3); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0046, 2); - - bcm43xx_rate_memory_init(bcm); - - /* Minimum Contention Window */ - if (phy->type == BCM43xx_PHYTYPE_B) - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000001f); - else - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0003, 0x0000000f); - /* Maximum Contention Window */ - bcm43xx_shm_write32(bcm, BCM43xx_SHM_WIRELESS, 0x0004, 0x000003ff); - - bcm43xx_gen_bssid(bcm); - bcm43xx_write_mac_bssid_templates(bcm); - - if (bcm->current_core->rev >= 5) - bcm43xx_write16(bcm, 0x043C, 0x000C); - - if (active_wlcore) { - if (bcm43xx_using_pio(bcm)) { - err = bcm43xx_pio_init(bcm); - } else { - err = bcm43xx_dma_init(bcm); - if (err == -ENOSYS) - err = bcm43xx_pio_init(bcm); - } - if (err) - goto err_chip_cleanup; - } - bcm43xx_write16(bcm, 0x0612, 0x0050); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0416, 0x0050); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0414, 0x01F4); - - if (active_wlcore) { - if (radio->initial_channel != 0xFF) - bcm43xx_radio_selectchannel(bcm, radio->initial_channel, 0); - } - - /* Don't enable MAC/IRQ here, as it will race with the IRQ handler. - * We enable it later. - */ - bcm->current_core->initialized = 1; -out: - return err; - -err_chip_cleanup: - bcm43xx_chip_cleanup(bcm); - goto out; -} - -static int bcm43xx_chipset_attach(struct bcm43xx_private *bcm) -{ - int err; - u16 pci_status; - - err = bcm43xx_pctl_set_crystal(bcm, 1); - if (err) - goto out; - err = bcm43xx_pci_read_config16(bcm, PCI_STATUS, &pci_status); - if (err) - goto out; - err = bcm43xx_pci_write_config16(bcm, PCI_STATUS, pci_status & ~PCI_STATUS_SIG_TARGET_ABORT); - -out: - return err; -} - -static void bcm43xx_chipset_detach(struct bcm43xx_private *bcm) -{ - bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); - bcm43xx_pctl_set_crystal(bcm, 0); -} - -static void bcm43xx_pcicore_broadcast_value(struct bcm43xx_private *bcm, - u32 address, - u32 data) -{ - bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_ADDR, address); - bcm43xx_write32(bcm, BCM43xx_PCICORE_BCAST_DATA, data); -} - -static int bcm43xx_pcicore_commit_settings(struct bcm43xx_private *bcm) -{ - int err = 0; - - bcm->irq_savedstate = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - - if (bcm->core_chipcommon.available) { - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err) - goto out; - - bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); - - /* this function is always called when a PCI core is mapped */ - err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (err) - goto out; - } else - bcm43xx_pcicore_broadcast_value(bcm, 0xfd8, 0x00000000); - - bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - -out: - return err; -} - -static u32 bcm43xx_pcie_reg_read(struct bcm43xx_private *bcm, u32 address) -{ - bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); - return bcm43xx_read32(bcm, BCM43xx_PCIECORE_REG_DATA); -} - -static void bcm43xx_pcie_reg_write(struct bcm43xx_private *bcm, u32 address, - u32 data) -{ - bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_ADDR, address); - bcm43xx_write32(bcm, BCM43xx_PCIECORE_REG_DATA, data); -} - -static void bcm43xx_pcie_mdio_write(struct bcm43xx_private *bcm, u8 dev, u8 reg, - u16 data) -{ - int i; - - bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0x0082); - bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_DATA, BCM43xx_PCIE_MDIO_ST | - BCM43xx_PCIE_MDIO_WT | (dev << BCM43xx_PCIE_MDIO_DEV) | - (reg << BCM43xx_PCIE_MDIO_REG) | BCM43xx_PCIE_MDIO_TA | - data); - udelay(10); - - for (i = 0; i < 10; i++) { - if (bcm43xx_read32(bcm, BCM43xx_PCIECORE_MDIO_CTL) & - BCM43xx_PCIE_MDIO_TC) - break; - msleep(1); - } - bcm43xx_write32(bcm, BCM43xx_PCIECORE_MDIO_CTL, 0); -} - -/* Make an I/O Core usable. "core_mask" is the bitmask of the cores to enable. - * To enable core 0, pass a core_mask of 1<<0 - */ -static int bcm43xx_setup_backplane_pci_connection(struct bcm43xx_private *bcm, - u32 core_mask) -{ - u32 backplane_flag_nr; - u32 value; - struct bcm43xx_coreinfo *old_core; - int err = 0; - - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBTPSFLAG); - backplane_flag_nr = value & BCM43xx_BACKPLANE_FLAG_NR_MASK; - - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_pci); - if (err) - goto out; - - if (bcm->current_core->rev < 6 && - bcm->current_core->id == BCM43xx_COREID_PCI) { - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBINTVEC); - value |= (1 << backplane_flag_nr); - bcm43xx_write32(bcm, BCM43xx_CIR_SBINTVEC, value); - } else { - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCICFG_ICR, &value); - if (err) { - printk(KERN_ERR PFX "Error: ICR setup failure!\n"); - goto out_switch_back; - } - value |= core_mask << 8; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCICFG_ICR, value); - if (err) { - printk(KERN_ERR PFX "Error: ICR setup failure!\n"); - goto out_switch_back; - } - } - - if (bcm->current_core->id == BCM43xx_COREID_PCI) { - value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); - value |= BCM43xx_SBTOPCI2_PREFETCH | BCM43xx_SBTOPCI2_BURST; - bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); - - if (bcm->current_core->rev < 5) { - value = bcm43xx_read32(bcm, BCM43xx_CIR_SBIMCONFIGLOW); - value |= (2 << BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_SHIFT) - & BCM43xx_SBIMCONFIGLOW_SERVICE_TOUT_MASK; - value |= (3 << BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_SHIFT) - & BCM43xx_SBIMCONFIGLOW_REQUEST_TOUT_MASK; - bcm43xx_write32(bcm, BCM43xx_CIR_SBIMCONFIGLOW, value); - err = bcm43xx_pcicore_commit_settings(bcm); - assert(err == 0); - } else if (bcm->current_core->rev >= 11) { - value = bcm43xx_read32(bcm, BCM43xx_PCICORE_SBTOPCI2); - value |= BCM43xx_SBTOPCI2_MEMREAD_MULTI; - bcm43xx_write32(bcm, BCM43xx_PCICORE_SBTOPCI2, value); - } - } else { - if (bcm->current_core->rev == 0 || bcm->current_core->rev == 1) { - value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_TLP_WORKAROUND); - value |= 0x8; - bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_TLP_WORKAROUND, - value); - } - if (bcm->current_core->rev == 0) { - bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, - BCM43xx_SERDES_RXTIMER, 0x8128); - bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, - BCM43xx_SERDES_CDR, 0x0100); - bcm43xx_pcie_mdio_write(bcm, BCM43xx_MDIO_SERDES_RX, - BCM43xx_SERDES_CDR_BW, 0x1466); - } else if (bcm->current_core->rev == 1) { - value = bcm43xx_pcie_reg_read(bcm, BCM43xx_PCIE_DLLP_LINKCTL); - value |= 0x40; - bcm43xx_pcie_reg_write(bcm, BCM43xx_PCIE_DLLP_LINKCTL, - value); - } - } -out_switch_back: - err = bcm43xx_switch_core(bcm, old_core); -out: - return err; -} - -static void bcm43xx_periodic_every120sec(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (phy->type != BCM43xx_PHYTYPE_G || phy->rev < 2) - return; - - bcm43xx_mac_suspend(bcm); - bcm43xx_phy_lo_g_measure(bcm); - bcm43xx_mac_enable(bcm); -} - -static void bcm43xx_periodic_every60sec(struct bcm43xx_private *bcm) -{ - bcm43xx_phy_lo_mark_all_unused(bcm); - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - bcm43xx_mac_suspend(bcm); - bcm43xx_calc_nrssi_slope(bcm); - bcm43xx_mac_enable(bcm); - } -} - -static void bcm43xx_periodic_every30sec(struct bcm43xx_private *bcm) -{ - /* Update device statistics. */ - bcm43xx_calculate_link_quality(bcm); -} - -static void bcm43xx_periodic_every15sec(struct bcm43xx_private *bcm) -{ - bcm43xx_phy_xmitpower(bcm); //FIXME: unless scanning? - //TODO for APHY (temperature?) -} - -static void bcm43xx_periodic_every1sec(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int radio_hw_enable; - - /* check if radio hardware enabled status changed */ - radio_hw_enable = bcm43xx_is_hw_radio_enabled(bcm); - if (unlikely(bcm->radio_hw_enable != radio_hw_enable)) { - bcm->radio_hw_enable = radio_hw_enable; - printk(KERN_INFO PFX "Radio hardware status changed to %s\n", - (radio_hw_enable == 0) ? "disabled" : "enabled"); - bcm43xx_leds_update(bcm, 0); - } - if (phy->type == BCM43xx_PHYTYPE_G) { - //TODO: update_aci_moving_average - if (radio->aci_enable && radio->aci_wlan_automatic) { - bcm43xx_mac_suspend(bcm); - if (!radio->aci_enable && 1 /*TODO: not scanning? */) { - if (0 /*TODO: bunch of conditions*/) { - bcm43xx_radio_set_interference_mitigation(bcm, - BCM43xx_RADIO_INTERFMODE_MANUALWLAN); - } - } else if (1/*TODO*/) { - /* - if ((aci_average > 1000) && !(bcm43xx_radio_aci_scan(bcm))) { - bcm43xx_radio_set_interference_mitigation(bcm, - BCM43xx_RADIO_INTERFMODE_NONE); - } - */ - } - bcm43xx_mac_enable(bcm); - } else if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN && - phy->rev == 1) { - //TODO: implement rev1 workaround - } - } -} - -static void do_periodic_work(struct bcm43xx_private *bcm) -{ - if (bcm->periodic_state % 120 == 0) - bcm43xx_periodic_every120sec(bcm); - if (bcm->periodic_state % 60 == 0) - bcm43xx_periodic_every60sec(bcm); - if (bcm->periodic_state % 30 == 0) - bcm43xx_periodic_every30sec(bcm); - if (bcm->periodic_state % 15 == 0) - bcm43xx_periodic_every15sec(bcm); - bcm43xx_periodic_every1sec(bcm); - - schedule_delayed_work(&bcm->periodic_work, HZ); -} - -static void bcm43xx_periodic_work_handler(struct work_struct *work) -{ - struct bcm43xx_private *bcm = - container_of(work, struct bcm43xx_private, periodic_work.work); - struct net_device *net_dev = bcm->net_dev; - unsigned long flags; - u32 savedirqs = 0; - unsigned long orig_trans_start = 0; - - mutex_lock(&bcm->mutex); - /* keep from doing and rearming periodic work if shutting down */ - if (bcm43xx_status(bcm) == BCM43xx_STAT_UNINIT) - goto unlock_mutex; - if (unlikely(bcm->periodic_state % 60 == 0)) { - /* Periodic work will take a long time, so we want it to - * be preemtible. - */ - - netif_tx_lock_bh(net_dev); - /* We must fake a started transmission here, as we are going to - * disable TX. If we wouldn't fake a TX, it would be possible to - * trigger the netdev watchdog, if the last real TX is already - * some time on the past (slightly less than 5secs) - */ - orig_trans_start = net_dev->trans_start; - net_dev->trans_start = jiffies; - netif_stop_queue(net_dev); - netif_tx_unlock_bh(net_dev); - - spin_lock_irqsave(&bcm->irq_lock, flags); - bcm43xx_mac_suspend(bcm); - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_freeze_txqueues(bcm); - savedirqs = bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - bcm43xx_synchronize_irq(bcm); - } else { - /* Periodic work should take short time, so we want low - * locking overhead. - */ - spin_lock_irqsave(&bcm->irq_lock, flags); - } - - do_periodic_work(bcm); - - if (unlikely(bcm->periodic_state % 60 == 0)) { - spin_lock_irqsave(&bcm->irq_lock, flags); - tasklet_enable(&bcm->isr_tasklet); - bcm43xx_interrupt_enable(bcm, savedirqs); - if (bcm43xx_using_pio(bcm)) - bcm43xx_pio_thaw_txqueues(bcm); - bcm43xx_mac_enable(bcm); - netif_wake_queue(bcm->net_dev); - net_dev->trans_start = orig_trans_start; - } - mmiowb(); - bcm->periodic_state++; - spin_unlock_irqrestore(&bcm->irq_lock, flags); -unlock_mutex: - mutex_unlock(&bcm->mutex); -} - -void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm) -{ - struct delayed_work *work = &bcm->periodic_work; - - assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - INIT_DELAYED_WORK(work, bcm43xx_periodic_work_handler); - schedule_delayed_work(work, 0); -} - -static void bcm43xx_security_init(struct bcm43xx_private *bcm) -{ - bcm->security_offset = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - 0x0056) * 2; - bcm43xx_clear_keys(bcm); -} - -static int bcm43xx_rng_read(struct hwrng *rng, u32 *data) -{ - struct bcm43xx_private *bcm = (struct bcm43xx_private *)rng->priv; - unsigned long flags; - - spin_lock_irqsave(&(bcm)->irq_lock, flags); - *data = bcm43xx_read16(bcm, BCM43xx_MMIO_RNG); - spin_unlock_irqrestore(&(bcm)->irq_lock, flags); - - return (sizeof(u16)); -} - -static void bcm43xx_rng_exit(struct bcm43xx_private *bcm) -{ - hwrng_unregister(&bcm->rng); -} - -static int bcm43xx_rng_init(struct bcm43xx_private *bcm) -{ - int err; - - snprintf(bcm->rng_name, ARRAY_SIZE(bcm->rng_name), - "%s_%s", KBUILD_MODNAME, bcm->net_dev->name); - bcm->rng.name = bcm->rng_name; - bcm->rng.data_read = bcm43xx_rng_read; - bcm->rng.priv = (unsigned long)bcm; - err = hwrng_register(&bcm->rng); - if (err) - printk(KERN_ERR PFX "RNG init failed (%d)\n", err); - - return err; -} - -void bcm43xx_cancel_work(struct bcm43xx_private *bcm) -{ - /* The system must be unlocked when this routine is entered. - * If not, the next 2 steps may deadlock */ - cancel_work_sync(&bcm->restart_work); - cancel_delayed_work_sync(&bcm->periodic_work); -} - -static int bcm43xx_shutdown_all_wireless_cores(struct bcm43xx_private *bcm) -{ - int ret = 0; - int i, err; - struct bcm43xx_coreinfo *core; - - bcm43xx_set_status(bcm, BCM43xx_STAT_SHUTTINGDOWN); - for (i = 0; i < bcm->nr_80211_available; i++) { - core = &(bcm->core_80211[i]); - assert(core->available); - if (!core->initialized) - continue; - err = bcm43xx_switch_core(bcm, core); - if (err) { - dprintk(KERN_ERR PFX "shutdown_all_wireless_cores " - "switch_core failed (%d)\n", err); - ret = err; - continue; - } - bcm43xx_interrupt_disable(bcm, BCM43xx_IRQ_ALL); - bcm43xx_read32(bcm, BCM43xx_MMIO_GEN_IRQ_REASON); /* dummy read */ - bcm43xx_wireless_core_cleanup(bcm); - if (core == bcm->active_80211_core) - bcm->active_80211_core = NULL; - } - free_irq(bcm->irq, bcm); - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - - return ret; -} - -/* This is the opposite of bcm43xx_init_board() */ -static void bcm43xx_free_board(struct bcm43xx_private *bcm) -{ - bcm43xx_rng_exit(bcm); - bcm43xx_sysfs_unregister(bcm); - - mutex_lock(&(bcm)->mutex); - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - mutex_unlock(&(bcm)->mutex); - - bcm43xx_cancel_work(bcm); - - mutex_lock(&(bcm)->mutex); - bcm43xx_shutdown_all_wireless_cores(bcm); - bcm43xx_pctl_set_crystal(bcm, 0); - mutex_unlock(&(bcm)->mutex); -} - -static void prepare_phydata_for_init(struct bcm43xx_phyinfo *phy) -{ - phy->antenna_diversity = 0xFFFF; - memset(phy->minlowsig, 0xFF, sizeof(phy->minlowsig)); - memset(phy->minlowsigpos, 0, sizeof(phy->minlowsigpos)); - - /* Flags */ - phy->calibrated = 0; - phy->is_locked = 0; - - if (phy->_lo_pairs) { - memset(phy->_lo_pairs, 0, - sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT); - } - memset(phy->loopback_gain, 0, sizeof(phy->loopback_gain)); -} - -static void prepare_radiodata_for_init(struct bcm43xx_private *bcm, - struct bcm43xx_radioinfo *radio) -{ - int i; - - /* Set default attenuation values. */ - radio->baseband_atten = bcm43xx_default_baseband_attenuation(bcm); - radio->radio_atten = bcm43xx_default_radio_attenuation(bcm); - radio->txctl1 = bcm43xx_default_txctl1(bcm); - radio->txctl2 = 0xFFFF; - radio->txpwr_offset = 0; - - /* NRSSI */ - radio->nrssislope = 0; - for (i = 0; i < ARRAY_SIZE(radio->nrssi); i++) - radio->nrssi[i] = -1000; - for (i = 0; i < ARRAY_SIZE(radio->nrssi_lt); i++) - radio->nrssi_lt[i] = i; - - radio->lofcal = 0xFFFF; - radio->initval = 0xFFFF; - - radio->aci_enable = 0; - radio->aci_wlan_automatic = 0; - radio->aci_hw_rssi = 0; -} - -static void prepare_priv_for_init(struct bcm43xx_private *bcm) -{ - int i; - struct bcm43xx_coreinfo *core; - struct bcm43xx_coreinfo_80211 *wlext; - - assert(!bcm->active_80211_core); - - bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); - - /* Flags */ - bcm->was_initialized = 0; - bcm->reg124_set_0x4 = 0; - - /* Stats */ - memset(&bcm->stats, 0, sizeof(bcm->stats)); - - /* Wireless core data */ - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - core = &(bcm->core_80211[i]); - wlext = core->priv; - - if (!core->available) - continue; - assert(wlext == &(bcm->core_80211_ext[i])); - - prepare_phydata_for_init(&wlext->phy); - prepare_radiodata_for_init(bcm, &wlext->radio); - } - - /* IRQ related flags */ - bcm->irq_reason = 0; - memset(bcm->dma_reason, 0, sizeof(bcm->dma_reason)); - bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; - - bcm->mac_suspended = 1; - - /* Noise calculation context */ - memset(&bcm->noisecalc, 0, sizeof(bcm->noisecalc)); - - /* Periodic work context */ - bcm->periodic_state = 0; -} - -static int wireless_core_up(struct bcm43xx_private *bcm, - int active_wlcore) -{ - int err; - - if (!bcm43xx_core_enabled(bcm)) - bcm43xx_wireless_core_reset(bcm, 1); - if (!active_wlcore) - bcm43xx_wireless_core_mark_inactive(bcm); - err = bcm43xx_wireless_core_init(bcm, active_wlcore); - if (err) - goto out; - if (!active_wlcore) - bcm43xx_radio_turn_off(bcm); -out: - return err; -} - -/* Select and enable the "to be used" wireless core. - * Locking: bcm->mutex must be aquired before calling this. - * bcm->irq_lock must not be aquired. - */ -int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, - int phytype) -{ - int i, err; - struct bcm43xx_coreinfo *active_core = NULL; - struct bcm43xx_coreinfo_80211 *active_wlext = NULL; - struct bcm43xx_coreinfo *core; - struct bcm43xx_coreinfo_80211 *wlext; - int adjust_active_sbtmstatelow = 0; - - might_sleep(); - - if (phytype < 0) { - /* If no phytype is requested, select the first core. */ - assert(bcm->core_80211[0].available); - wlext = bcm->core_80211[0].priv; - phytype = wlext->phy.type; - } - /* Find the requested core. */ - for (i = 0; i < bcm->nr_80211_available; i++) { - core = &(bcm->core_80211[i]); - wlext = core->priv; - if (wlext->phy.type == phytype) { - active_core = core; - active_wlext = wlext; - break; - } - } - if (!active_core) - return -ESRCH; /* No such PHYTYPE on this board. */ - - if (bcm->active_80211_core) { - /* We already selected a wl core in the past. - * So first clean up everything. - */ - dprintk(KERN_INFO PFX "select_wireless_core: cleanup\n"); - ieee80211softmac_stop(bcm->net_dev); - bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); - err = bcm43xx_disable_interrupts_sync(bcm); - assert(!err); - tasklet_enable(&bcm->isr_tasklet); - err = bcm43xx_shutdown_all_wireless_cores(bcm); - if (err) - goto error; - /* Ok, everything down, continue to re-initialize. */ - bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZING); - } - - /* Reset all data structures. */ - prepare_priv_for_init(bcm); - - err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_FAST); - if (err) - goto error; - - /* Mark all unused cores "inactive". */ - for (i = 0; i < bcm->nr_80211_available; i++) { - core = &(bcm->core_80211[i]); - wlext = core->priv; - - if (core == active_core) - continue; - err = bcm43xx_switch_core(bcm, core); - if (err) { - dprintk(KERN_ERR PFX "Could not switch to inactive " - "802.11 core (%d)\n", err); - goto error; - } - err = wireless_core_up(bcm, 0); - if (err) { - dprintk(KERN_ERR PFX "core_up for inactive 802.11 core " - "failed (%d)\n", err); - goto error; - } - adjust_active_sbtmstatelow = 1; - } - - /* Now initialize the active 802.11 core. */ - err = bcm43xx_switch_core(bcm, active_core); - if (err) { - dprintk(KERN_ERR PFX "Could not switch to active " - "802.11 core (%d)\n", err); - goto error; - } - if (adjust_active_sbtmstatelow && - active_wlext->phy.type == BCM43xx_PHYTYPE_G) { - u32 sbtmstatelow; - - sbtmstatelow = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - sbtmstatelow |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, sbtmstatelow); - } - err = wireless_core_up(bcm, 1); - if (err) { - dprintk(KERN_ERR PFX "core_up for active 802.11 core " - "failed (%d)\n", err); - goto error; - } - err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_DYNAMIC); - if (err) - goto error; - bcm->active_80211_core = active_core; - - bcm43xx_macfilter_clear(bcm, BCM43xx_MACFILTER_ASSOC); - bcm43xx_macfilter_set(bcm, BCM43xx_MACFILTER_SELF, (u8 *)(bcm->net_dev->dev_addr)); - bcm43xx_security_init(bcm); - drain_txstatus_queue(bcm); - ieee80211softmac_start(bcm->net_dev); - - /* Let's go! Be careful after enabling the IRQs. - * Don't switch cores, for example. - */ - bcm43xx_mac_enable(bcm); - bcm43xx_set_status(bcm, BCM43xx_STAT_INITIALIZED); - err = bcm43xx_initialize_irq(bcm); - if (err) - goto error; - bcm43xx_interrupt_enable(bcm, bcm->irq_savedstate); - - dprintk(KERN_INFO PFX "Selected 802.11 core (phytype %d)\n", - active_wlext->phy.type); - - return 0; - -error: - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); - return err; -} - -static int bcm43xx_init_board(struct bcm43xx_private *bcm) -{ - int err; - - mutex_lock(&(bcm)->mutex); - - tasklet_enable(&bcm->isr_tasklet); - err = bcm43xx_pctl_set_crystal(bcm, 1); - if (err) - goto err_tasklet; - err = bcm43xx_pctl_init(bcm); - if (err) - goto err_crystal_off; - err = bcm43xx_select_wireless_core(bcm, -1); - if (err) - goto err_crystal_off; - err = bcm43xx_sysfs_register(bcm); - if (err) - goto err_wlshutdown; - err = bcm43xx_rng_init(bcm); - if (err) - goto err_sysfs_unreg; - bcm43xx_periodic_tasks_setup(bcm); - - /*FIXME: This should be handled by softmac instead. */ - schedule_delayed_work(&bcm->softmac->associnfo.work, 0); - -out: - mutex_unlock(&(bcm)->mutex); - - return err; - -err_sysfs_unreg: - bcm43xx_sysfs_unregister(bcm); -err_wlshutdown: - bcm43xx_shutdown_all_wireless_cores(bcm); -err_crystal_off: - bcm43xx_pctl_set_crystal(bcm, 0); -err_tasklet: - tasklet_disable(&bcm->isr_tasklet); - goto out; -} - -static void bcm43xx_detach_board(struct bcm43xx_private *bcm) -{ - struct pci_dev *pci_dev = bcm->pci_dev; - int i; - - bcm43xx_chipset_detach(bcm); - /* Do _not_ access the chip, after it is detached. */ - pci_iounmap(pci_dev, bcm->mmio_addr); - pci_release_regions(pci_dev); - pci_disable_device(pci_dev); - - /* Free allocated structures/fields */ - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - kfree(bcm->core_80211_ext[i].phy._lo_pairs); - if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl) - kfree(bcm->core_80211_ext[i].phy.tssi2dbm); - } -} - -static int bcm43xx_read_phyinfo(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 value; - u8 phy_analog; - u8 phy_type; - u8 phy_rev; - int phy_rev_ok = 1; - void *p; - - value = bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); - - phy_analog = (value & 0xF000) >> 12; - phy_type = (value & 0x0F00) >> 8; - phy_rev = (value & 0x000F); - - dprintk(KERN_INFO PFX "Detected PHY: Analog: %x, Type %x, Revision %x\n", - phy_analog, phy_type, phy_rev); - - switch (phy_type) { - case BCM43xx_PHYTYPE_A: - if (phy_rev >= 4) - phy_rev_ok = 0; - /*FIXME: We need to switch the ieee->modulation, etc.. flags, - * if we switch 80211 cores after init is done. - * As we do not implement on the fly switching between - * wireless cores, I will leave this as a future task. - */ - bcm->ieee->modulation = IEEE80211_OFDM_MODULATION; - bcm->ieee->mode = IEEE_A; - bcm->ieee->freq_band = IEEE80211_52GHZ_BAND | - IEEE80211_24GHZ_BAND; - break; - case BCM43xx_PHYTYPE_B: - if (phy_rev != 2 && phy_rev != 4 && phy_rev != 6 && phy_rev != 7) - phy_rev_ok = 0; - bcm->ieee->modulation = IEEE80211_CCK_MODULATION; - bcm->ieee->mode = IEEE_B; - bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; - break; - case BCM43xx_PHYTYPE_G: - if (phy_rev > 8) - phy_rev_ok = 0; - bcm->ieee->modulation = IEEE80211_OFDM_MODULATION | - IEEE80211_CCK_MODULATION; - bcm->ieee->mode = IEEE_G; - bcm->ieee->freq_band = IEEE80211_24GHZ_BAND; - break; - default: - printk(KERN_ERR PFX "Error: Unknown PHY Type %x\n", - phy_type); - return -ENODEV; - }; - bcm->ieee->perfect_rssi = RX_RSSI_MAX; - bcm->ieee->worst_rssi = 0; - if (!phy_rev_ok) { - printk(KERN_WARNING PFX "Invalid PHY Revision %x\n", - phy_rev); - } - - phy->analog = phy_analog; - phy->type = phy_type; - phy->rev = phy_rev; - if ((phy_type == BCM43xx_PHYTYPE_B) || (phy_type == BCM43xx_PHYTYPE_G)) { - p = kzalloc(sizeof(struct bcm43xx_lopair) * BCM43xx_LO_COUNT, - GFP_KERNEL); - if (!p) - return -ENOMEM; - phy->_lo_pairs = p; - } - - return 0; -} - -static int bcm43xx_attach_board(struct bcm43xx_private *bcm) -{ - struct pci_dev *pci_dev = bcm->pci_dev; - struct net_device *net_dev = bcm->net_dev; - int err; - int i; - u32 coremask; - - err = pci_enable_device(pci_dev); - if (err) { - printk(KERN_ERR PFX "pci_enable_device() failed\n"); - goto out; - } - err = pci_request_regions(pci_dev, KBUILD_MODNAME); - if (err) { - printk(KERN_ERR PFX "pci_request_regions() failed\n"); - goto err_pci_disable; - } - /* enable PCI bus-mastering */ - pci_set_master(pci_dev); - bcm->mmio_addr = pci_iomap(pci_dev, 0, ~0UL); - if (!bcm->mmio_addr) { - printk(KERN_ERR PFX "pci_iomap() failed\n"); - err = -EIO; - goto err_pci_release; - } - net_dev->base_addr = (unsigned long)bcm->mmio_addr; - - err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_VENDOR_ID, - &bcm->board_vendor); - if (err) - goto err_iounmap; - err = bcm43xx_pci_read_config16(bcm, PCI_SUBSYSTEM_ID, - &bcm->board_type); - if (err) - goto err_iounmap; - - bcm->board_revision = bcm->pci_dev->revision; - - err = bcm43xx_chipset_attach(bcm); - if (err) - goto err_iounmap; - err = bcm43xx_pctl_init(bcm); - if (err) - goto err_chipset_detach; - err = bcm43xx_probe_cores(bcm); - if (err) - goto err_chipset_detach; - - /* Attach all IO cores to the backplane. */ - coremask = 0; - for (i = 0; i < bcm->nr_80211_available; i++) - coremask |= (1 << bcm->core_80211[i].index); - //FIXME: Also attach some non80211 cores? - err = bcm43xx_setup_backplane_pci_connection(bcm, coremask); - if (err) { - printk(KERN_ERR PFX "Backplane->PCI connection failed!\n"); - goto err_chipset_detach; - } - - err = bcm43xx_sprom_extract(bcm); - if (err) - goto err_chipset_detach; - err = bcm43xx_leds_init(bcm); - if (err) - goto err_chipset_detach; - - for (i = 0; i < bcm->nr_80211_available; i++) { - err = bcm43xx_switch_core(bcm, &bcm->core_80211[i]); - assert(err != -ENODEV); - if (err) - goto err_80211_unwind; - - /* Enable the selected wireless core. - * Connect PHY only on the first core. - */ - bcm43xx_wireless_core_reset(bcm, (i == 0)); - - err = bcm43xx_read_phyinfo(bcm); - if (err && (i == 0)) - goto err_80211_unwind; - - err = bcm43xx_read_radioinfo(bcm); - if (err && (i == 0)) - goto err_80211_unwind; - - err = bcm43xx_validate_chip(bcm); - if (err && (i == 0)) - goto err_80211_unwind; - - bcm43xx_radio_turn_off(bcm); - err = bcm43xx_phy_init_tssi2dbm_table(bcm); - if (err) - goto err_80211_unwind; - bcm43xx_wireless_core_disable(bcm); - } - err = bcm43xx_geo_init(bcm); - if (err) - goto err_80211_unwind; - bcm43xx_pctl_set_crystal(bcm, 0); - - /* Set the MAC address in the networking subsystem */ - if (is_valid_ether_addr(bcm->sprom.et1macaddr)) - memcpy(bcm->net_dev->dev_addr, bcm->sprom.et1macaddr, 6); - else - memcpy(bcm->net_dev->dev_addr, bcm->sprom.il0macaddr, 6); - - snprintf(bcm->nick, IW_ESSID_MAX_SIZE, - "Broadcom %04X", bcm->chip_id); - - assert(err == 0); -out: - return err; - -err_80211_unwind: - for (i = 0; i < BCM43xx_MAX_80211_CORES; i++) { - kfree(bcm->core_80211_ext[i].phy._lo_pairs); - if (bcm->core_80211_ext[i].phy.dyn_tssi_tbl) - kfree(bcm->core_80211_ext[i].phy.tssi2dbm); - } -err_chipset_detach: - bcm43xx_chipset_detach(bcm); -err_iounmap: - pci_iounmap(pci_dev, bcm->mmio_addr); -err_pci_release: - pci_release_regions(pci_dev); -err_pci_disable: - pci_disable_device(pci_dev); - printk(KERN_ERR PFX "Unable to attach board\n"); - goto out; -} - -/* Do the Hardware IO operations to send the txb */ -static inline int bcm43xx_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - int err = -ENODEV; - - if (bcm43xx_using_pio(bcm)) - err = bcm43xx_pio_tx(bcm, txb); - else - err = bcm43xx_dma_tx(bcm, txb); - bcm->net_dev->trans_start = jiffies; - - return err; -} - -static void bcm43xx_ieee80211_set_chan(struct net_device *net_dev, - u8 channel) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct bcm43xx_radioinfo *radio; - unsigned long flags; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - bcm43xx_mac_suspend(bcm); - bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_mac_enable(bcm); - } else { - radio = bcm43xx_current_radio(bcm); - radio->initial_channel = channel; - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -} - -/* set_security() callback in struct ieee80211_device */ -static void bcm43xx_ieee80211_set_security(struct net_device *net_dev, - struct ieee80211_security *sec) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct ieee80211_security *secinfo = &bcm->ieee->sec; - unsigned long flags; - int keyidx; - - dprintk(KERN_INFO PFX "set security called"); - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx] = sec->encode_alg[keyidx]; - secinfo->key_sizes[keyidx] = sec->key_sizes[keyidx]; - memcpy(secinfo->keys[keyidx], sec->keys[keyidx], SCM_KEY_LEN); - } - - if (sec->flags & SEC_ACTIVE_KEY) { - secinfo->active_key = sec->active_key; - dprintk(", .active_key = %d", sec->active_key); - } - if (sec->flags & SEC_UNICAST_GROUP) { - secinfo->unicast_uses_group = sec->unicast_uses_group; - dprintk(", .unicast_uses_group = %d", sec->unicast_uses_group); - } - if (sec->flags & SEC_LEVEL) { - secinfo->level = sec->level; - dprintk(", .level = %d", sec->level); - } - if (sec->flags & SEC_ENABLED) { - secinfo->enabled = sec->enabled; - dprintk(", .enabled = %d", sec->enabled); - } - if (sec->flags & SEC_ENCRYPT) { - secinfo->encrypt = sec->encrypt; - dprintk(", .encrypt = %d", sec->encrypt); - } - if (sec->flags & SEC_AUTH_MODE) { - secinfo->auth_mode = sec->auth_mode; - dprintk(", .auth_mode = %d", sec->auth_mode); - } - dprintk("\n"); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED && - !bcm->ieee->host_encrypt) { - if (secinfo->enabled) { - /* upload WEP keys to hardware */ - char null_address[6] = { 0 }; - u8 algorithm = 0; - for (keyidx = 0; keyidxflags & (1<encode_alg[keyidx]) { - case SEC_ALG_NONE: algorithm = BCM43xx_SEC_ALGO_NONE; break; - case SEC_ALG_WEP: - algorithm = BCM43xx_SEC_ALGO_WEP; - if (secinfo->key_sizes[keyidx] == 13) - algorithm = BCM43xx_SEC_ALGO_WEP104; - break; - case SEC_ALG_TKIP: - FIXME(); - algorithm = BCM43xx_SEC_ALGO_TKIP; - break; - case SEC_ALG_CCMP: - FIXME(); - algorithm = BCM43xx_SEC_ALGO_AES; - break; - default: - assert(0); - break; - } - bcm43xx_key_write(bcm, keyidx, algorithm, sec->keys[keyidx], secinfo->key_sizes[keyidx], &null_address[0]); - bcm->key[keyidx].enabled = 1; - bcm->key[keyidx].algorithm = algorithm; - } - } else - bcm43xx_clear_keys(bcm); - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -} - -/* hard_start_xmit() callback in struct ieee80211_device */ -static int bcm43xx_ieee80211_hard_start_xmit(struct ieee80211_txb *txb, - struct net_device *net_dev, - int pri) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = -ENODEV; - unsigned long flags; - - spin_lock_irqsave(&bcm->irq_lock, flags); - if (likely(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED)) - err = bcm43xx_tx(bcm, txb); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - - if (unlikely(err)) - return NETDEV_TX_BUSY; - return NETDEV_TX_OK; -} - -static void bcm43xx_net_tx_timeout(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - - spin_lock_irqsave(&bcm->irq_lock, flags); - bcm43xx_controller_restart(bcm, "TX timeout"); - spin_unlock_irqrestore(&bcm->irq_lock, flags); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void bcm43xx_net_poll_controller(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - - local_irq_save(flags); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) - bcm43xx_interrupt_handler(bcm->irq, bcm); - local_irq_restore(flags); -} -#endif /* CONFIG_NET_POLL_CONTROLLER */ - -static int bcm43xx_net_open(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - return bcm43xx_init_board(bcm); -} - -static int bcm43xx_net_stop(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - ieee80211softmac_stop(net_dev); - err = bcm43xx_disable_interrupts_sync(bcm); - assert(!err); - bcm43xx_free_board(bcm); - bcm43xx_cancel_work(bcm); - - return 0; -} - -static int bcm43xx_init_private(struct bcm43xx_private *bcm, - struct net_device *net_dev, - struct pci_dev *pci_dev) -{ - bcm43xx_set_status(bcm, BCM43xx_STAT_UNINIT); - bcm->ieee = netdev_priv(net_dev); - bcm->softmac = ieee80211_priv(net_dev); - bcm->softmac->set_channel = bcm43xx_ieee80211_set_chan; - - bcm->irq_savedstate = BCM43xx_IRQ_INITIAL; - bcm->mac_suspended = 1; - bcm->pci_dev = pci_dev; - bcm->net_dev = net_dev; - bcm->bad_frames_preempt = modparam_bad_frames_preempt; - spin_lock_init(&bcm->irq_lock); - spin_lock_init(&bcm->leds_lock); - mutex_init(&bcm->mutex); - tasklet_init(&bcm->isr_tasklet, - (void (*)(unsigned long))bcm43xx_interrupt_tasklet, - (unsigned long)bcm); - tasklet_disable_nosync(&bcm->isr_tasklet); - if (modparam_pio) - bcm->__using_pio = 1; - bcm->rts_threshold = BCM43xx_DEFAULT_RTS_THRESHOLD; - - /* default to sw encryption for now */ - bcm->ieee->host_build_iv = 0; - bcm->ieee->host_encrypt = 1; - bcm->ieee->host_decrypt = 1; - - bcm->ieee->iw_mode = BCM43xx_INITIAL_IWMODE; - bcm->ieee->tx_headroom = sizeof(struct bcm43xx_txhdr); - bcm->ieee->set_security = bcm43xx_ieee80211_set_security; - bcm->ieee->hard_start_xmit = bcm43xx_ieee80211_hard_start_xmit; - - return 0; -} - -static int __devinit bcm43xx_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *net_dev; - struct bcm43xx_private *bcm; - int err; - -#ifdef DEBUG_SINGLE_DEVICE_ONLY - if (strcmp(pci_name(pdev), DEBUG_SINGLE_DEVICE_ONLY)) - return -ENODEV; -#endif - - net_dev = alloc_ieee80211softmac(sizeof(*bcm)); - if (!net_dev) { - printk(KERN_ERR PFX - "could not allocate ieee80211 device %s\n", - pci_name(pdev)); - err = -ENOMEM; - goto out; - } - /* initialize the net_device struct */ - SET_NETDEV_DEV(net_dev, &pdev->dev); - - net_dev->open = bcm43xx_net_open; - net_dev->stop = bcm43xx_net_stop; - net_dev->tx_timeout = bcm43xx_net_tx_timeout; -#ifdef CONFIG_NET_POLL_CONTROLLER - net_dev->poll_controller = bcm43xx_net_poll_controller; -#endif - net_dev->wireless_handlers = &bcm43xx_wx_handlers_def; - net_dev->irq = pdev->irq; - SET_ETHTOOL_OPS(net_dev, &bcm43xx_ethtool_ops); - - /* initialize the bcm43xx_private struct */ - bcm = bcm43xx_priv(net_dev); - memset(bcm, 0, sizeof(*bcm)); - err = bcm43xx_init_private(bcm, net_dev, pdev); - if (err) - goto err_free_netdev; - - pci_set_drvdata(pdev, net_dev); - - err = bcm43xx_attach_board(bcm); - if (err) - goto err_free_netdev; - - err = register_netdev(net_dev); - if (err) { - printk(KERN_ERR PFX "Cannot register net device, " - "aborting.\n"); - err = -ENOMEM; - goto err_detach_board; - } - - bcm43xx_debugfs_add_device(bcm); - - assert(err == 0); -out: - return err; - -err_detach_board: - bcm43xx_detach_board(bcm); -err_free_netdev: - free_ieee80211softmac(net_dev); - goto out; -} - -static void __devexit bcm43xx_remove_one(struct pci_dev *pdev) -{ - struct net_device *net_dev = pci_get_drvdata(pdev); - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - bcm43xx_debugfs_remove_device(bcm); - unregister_netdev(net_dev); - bcm43xx_detach_board(bcm); - free_ieee80211softmac(net_dev); -} - -/* Hard-reset the chip. Do not call this directly. - * Use bcm43xx_controller_restart() - */ -static void bcm43xx_chip_reset(struct work_struct *work) -{ - struct bcm43xx_private *bcm = - container_of(work, struct bcm43xx_private, restart_work); - struct bcm43xx_phyinfo *phy; - int err = -ENODEV; - - bcm43xx_cancel_work(bcm); - mutex_lock(&(bcm)->mutex); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - phy = bcm43xx_current_phy(bcm); - err = bcm43xx_select_wireless_core(bcm, phy->type); - if (!err) - bcm43xx_periodic_tasks_setup(bcm); - } - mutex_unlock(&(bcm)->mutex); - - printk(KERN_ERR PFX "Controller restart%s\n", - (err == 0) ? "ed" : " failed"); -} - -/* Hard-reset the chip. - * This can be called from interrupt or process context. - * bcm->irq_lock must be locked. - */ -void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason) -{ - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) - return; - printk(KERN_ERR PFX "Controller RESET (%s) ...\n", reason); - INIT_WORK(&bcm->restart_work, bcm43xx_chip_reset); - schedule_work(&bcm->restart_work); -} - -#ifdef CONFIG_PM - -static int bcm43xx_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *net_dev = pci_get_drvdata(pdev); - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - dprintk(KERN_INFO PFX "Suspending...\n"); - - netif_device_detach(net_dev); - bcm->was_initialized = 0; - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - bcm->was_initialized = 1; - ieee80211softmac_stop(net_dev); - err = bcm43xx_disable_interrupts_sync(bcm); - if (unlikely(err)) { - dprintk(KERN_ERR PFX "Suspend failed.\n"); - return -EAGAIN; - } - bcm->firmware_norelease = 1; - bcm43xx_free_board(bcm); - bcm->firmware_norelease = 0; - } - bcm43xx_chipset_detach(bcm); - - pci_save_state(pdev); - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - dprintk(KERN_INFO PFX "Device suspended.\n"); - - return 0; -} - -static int bcm43xx_resume(struct pci_dev *pdev) -{ - struct net_device *net_dev = pci_get_drvdata(pdev); - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = 0; - - dprintk(KERN_INFO PFX "Resuming...\n"); - - pci_set_power_state(pdev, 0); - err = pci_enable_device(pdev); - if (err) { - printk(KERN_ERR PFX "Failure with pci_enable_device!\n"); - return err; - } - pci_restore_state(pdev); - - bcm43xx_chipset_attach(bcm); - if (bcm->was_initialized) - err = bcm43xx_init_board(bcm); - if (err) { - printk(KERN_ERR PFX "Resume failed!\n"); - return err; - } - netif_device_attach(net_dev); - - dprintk(KERN_INFO PFX "Device resumed.\n"); - - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver bcm43xx_pci_driver = { - .name = KBUILD_MODNAME, - .id_table = bcm43xx_pci_tbl, - .probe = bcm43xx_init_one, - .remove = __devexit_p(bcm43xx_remove_one), -#ifdef CONFIG_PM - .suspend = bcm43xx_suspend, - .resume = bcm43xx_resume, -#endif /* CONFIG_PM */ -}; - -static int __init bcm43xx_init(void) -{ - printk(KERN_INFO KBUILD_MODNAME " driver\n"); - bcm43xx_debugfs_init(); - return pci_register_driver(&bcm43xx_pci_driver); -} - -static void __exit bcm43xx_exit(void) -{ - pci_unregister_driver(&bcm43xx_pci_driver); - bcm43xx_debugfs_exit(); -} - -module_init(bcm43xx_init) -module_exit(bcm43xx_exit) diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_main.h b/drivers/net/wireless/bcm43xx/bcm43xx_main.h deleted file mode 100644 index 14cfbeb582ef..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_main.h +++ /dev/null @@ -1,133 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_MAIN_H_ -#define BCM43xx_MAIN_H_ - -#include "bcm43xx.h" - -#define P4D_BYT3S(magic, nr_bytes) u8 __p4dding##magic[nr_bytes] -#define P4D_BYTES(line, nr_bytes) P4D_BYT3S(line, nr_bytes) -/* Magic helper macro to pad structures. Ignore those above. It's magic. */ -#define PAD_BYTES(nr_bytes) P4D_BYTES( __LINE__ , (nr_bytes)) - - -/* Lightweight function to convert a frequency (in Mhz) to a channel number. */ -static inline -u8 bcm43xx_freq_to_channel_a(int freq) -{ - return ((freq - 5000) / 5); -} -static inline -u8 bcm43xx_freq_to_channel_bg(int freq) -{ - u8 channel; - - if (freq == 2484) - channel = 14; - else - channel = (freq - 2407) / 5; - - return channel; -} -static inline -u8 bcm43xx_freq_to_channel(struct bcm43xx_private *bcm, - int freq) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) - return bcm43xx_freq_to_channel_a(freq); - return bcm43xx_freq_to_channel_bg(freq); -} - -/* Lightweight function to convert a channel number to a frequency (in Mhz). */ -static inline -int bcm43xx_channel_to_freq_a(u8 channel) -{ - return (5000 + (5 * channel)); -} -static inline -int bcm43xx_channel_to_freq_bg(u8 channel) -{ - int freq; - - if (channel == 14) - freq = 2484; - else - freq = 2407 + (5 * channel); - - return freq; -} -static inline -int bcm43xx_channel_to_freq(struct bcm43xx_private *bcm, - u8 channel) -{ - if (bcm43xx_current_phy(bcm)->type == BCM43xx_PHYTYPE_A) - return bcm43xx_channel_to_freq_a(channel); - return bcm43xx_channel_to_freq_bg(channel); -} - -void bcm43xx_tsf_read(struct bcm43xx_private *bcm, u64 *tsf); -void bcm43xx_tsf_write(struct bcm43xx_private *bcm, u64 tsf); - -void bcm43xx_set_iwmode(struct bcm43xx_private *bcm, - int iw_mode); - -u32 bcm43xx_shm_read32(struct bcm43xx_private *bcm, - u16 routing, u16 offset); -u16 bcm43xx_shm_read16(struct bcm43xx_private *bcm, - u16 routing, u16 offset); -void bcm43xx_shm_write32(struct bcm43xx_private *bcm, - u16 routing, u16 offset, - u32 value); -void bcm43xx_shm_write16(struct bcm43xx_private *bcm, - u16 routing, u16 offset, - u16 value); - -void bcm43xx_dummy_transmission(struct bcm43xx_private *bcm); - -int bcm43xx_switch_core(struct bcm43xx_private *bcm, struct bcm43xx_coreinfo *new_core); - -int bcm43xx_select_wireless_core(struct bcm43xx_private *bcm, - int phytype); - -void bcm43xx_wireless_core_reset(struct bcm43xx_private *bcm, int connect_phy); - -void bcm43xx_mac_suspend(struct bcm43xx_private *bcm); -void bcm43xx_mac_enable(struct bcm43xx_private *bcm); - -void bcm43xx_cancel_work(struct bcm43xx_private *bcm); -void bcm43xx_periodic_tasks_setup(struct bcm43xx_private *bcm); - -void bcm43xx_controller_restart(struct bcm43xx_private *bcm, const char *reason); - -int bcm43xx_sprom_read(struct bcm43xx_private *bcm, u16 *sprom); -int bcm43xx_sprom_write(struct bcm43xx_private *bcm, const u16 *sprom); - -#endif /* BCM43xx_MAIN_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c b/drivers/net/wireless/bcm43xx/bcm43xx_phy.c deleted file mode 100644 index af3de3343650..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.c +++ /dev/null @@ -1,2346 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include - -#include "bcm43xx.h" -#include "bcm43xx_phy.h" -#include "bcm43xx_main.h" -#include "bcm43xx_radio.h" -#include "bcm43xx_ilt.h" -#include "bcm43xx_power.h" - - -static const s8 bcm43xx_tssi2dbm_b_table[] = { - 0x4D, 0x4C, 0x4B, 0x4A, - 0x4A, 0x49, 0x48, 0x47, - 0x47, 0x46, 0x45, 0x45, - 0x44, 0x43, 0x42, 0x42, - 0x41, 0x40, 0x3F, 0x3E, - 0x3D, 0x3C, 0x3B, 0x3A, - 0x39, 0x38, 0x37, 0x36, - 0x35, 0x34, 0x32, 0x31, - 0x30, 0x2F, 0x2D, 0x2C, - 0x2B, 0x29, 0x28, 0x26, - 0x25, 0x23, 0x21, 0x1F, - 0x1D, 0x1A, 0x17, 0x14, - 0x10, 0x0C, 0x06, 0x00, - -7, -7, -7, -7, - -7, -7, -7, -7, - -7, -7, -7, -7, -}; - -static const s8 bcm43xx_tssi2dbm_g_table[] = { - 77, 77, 77, 76, - 76, 76, 75, 75, - 74, 74, 73, 73, - 73, 72, 72, 71, - 71, 70, 70, 69, - 68, 68, 67, 67, - 66, 65, 65, 64, - 63, 63, 62, 61, - 60, 59, 58, 57, - 56, 55, 54, 53, - 52, 50, 49, 47, - 45, 43, 40, 37, - 33, 28, 22, 14, - 5, -7, -20, -20, - -20, -20, -20, -20, - -20, -20, -20, -20, -}; - -static void bcm43xx_phy_initg(struct bcm43xx_private *bcm); - - -static inline -void bcm43xx_voluntary_preempt(void) -{ - assert(!in_atomic() && !in_irq() && - !in_interrupt() && !irqs_disabled()); -#ifndef CONFIG_PREEMPT - cond_resched(); -#endif /* CONFIG_PREEMPT */ -} - -void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - assert(irqs_disabled()); - if (bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD) == 0x00000000) { - phy->is_locked = 0; - return; - } - if (bcm->current_core->rev < 3) { - bcm43xx_mac_suspend(bcm); - spin_lock(&phy->lock); - } else { - if (bcm->ieee->iw_mode != IW_MODE_MASTER) - bcm43xx_power_saving_ctl_bits(bcm, -1, 1); - } - phy->is_locked = 1; -} - -void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - assert(irqs_disabled()); - if (bcm->current_core->rev < 3) { - if (phy->is_locked) { - spin_unlock(&phy->lock); - bcm43xx_mac_enable(bcm); - } - } else { - if (bcm->ieee->iw_mode != IW_MODE_MASTER) - bcm43xx_power_saving_ctl_bits(bcm, -1, -1); - } - phy->is_locked = 0; -} - -u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset) -{ - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); - return bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_DATA); -} - -void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val) -{ - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_CONTROL, offset); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_DATA, val); -} - -void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); /* Dummy read. */ - if (phy->calibrated) - return; - if (phy->type == BCM43xx_PHYTYPE_G && phy->rev == 1) { - bcm43xx_wireless_core_reset(bcm, 0); - bcm43xx_phy_initg(bcm); - bcm43xx_wireless_core_reset(bcm, 1); - } - phy->calibrated = 1; -} - -/* Connect the PHY - * http://bcm-specs.sipsolutions.net/SetPHY - */ -int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u32 flags; - - if (bcm->current_core->rev < 5) - goto out; - - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATEHIGH); - if (connect) { - if (!(flags & BCM43xx_SBTMSTATEHIGH_G_PHY_AVAIL)) - return -ENODEV; - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - flags |= BCM43xx_SBTMSTATELOW_G_MODE_ENABLE; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); - } else { - if (!(flags & BCM43xx_SBTMSTATEHIGH_A_PHY_AVAIL)) - return -ENODEV; - flags = bcm43xx_read32(bcm, BCM43xx_CIR_SBTMSTATELOW); - flags &= ~BCM43xx_SBTMSTATELOW_G_MODE_ENABLE; - bcm43xx_write32(bcm, BCM43xx_CIR_SBTMSTATELOW, flags); - } -out: - phy->connected = connect; - if (connect) - dprintk(KERN_INFO PFX "PHY connected\n"); - else - dprintk(KERN_INFO PFX "PHY disconnected\n"); - - return 0; -} - -/* intialize B PHY power control - * as described in http://bcm-specs.sipsolutions.net/InitPowerControl - */ -static void bcm43xx_phy_init_pctl(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 saved_batt = 0, saved_ratt = 0, saved_txctl1 = 0; - int must_reset_txpower = 0; - - assert(phy->type != BCM43xx_PHYTYPE_A); - if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type == 0x0416)) - return; - - bcm43xx_phy_write(bcm, 0x0028, 0x8018); - bcm43xx_write16(bcm, 0x03E6, bcm43xx_read16(bcm, 0x03E6) & 0xFFDF); - - if (phy->type == BCM43xx_PHYTYPE_G) { - if (!phy->connected) - return; - bcm43xx_phy_write(bcm, 0x047A, 0xC111); - } - if (phy->savedpctlreg != 0xFFFF) - return; - - if (phy->type == BCM43xx_PHYTYPE_B && - phy->rev >= 2 && - radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0076, - bcm43xx_radio_read16(bcm, 0x0076) | 0x0084); - } else { - saved_batt = radio->baseband_atten; - saved_ratt = radio->radio_atten; - saved_txctl1 = radio->txctl1; - if ((radio->revision >= 6) && (radio->revision <= 8) - && /*FIXME: incomplete specs for 5 < revision < 9 */ 0) - bcm43xx_radio_set_txpower_bg(bcm, 0xB, 0x1F, 0); - else - bcm43xx_radio_set_txpower_bg(bcm, 0xB, 9, 0); - must_reset_txpower = 1; - } - bcm43xx_dummy_transmission(bcm); - - phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_PCTL); - - if (must_reset_txpower) - bcm43xx_radio_set_txpower_bg(bcm, saved_batt, saved_ratt, saved_txctl1); - else - bcm43xx_radio_write16(bcm, 0x0076, bcm43xx_radio_read16(bcm, 0x0076) & 0xFF7B); - bcm43xx_radio_clear_tssi(bcm); -} - -static void bcm43xx_phy_agcsetup(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 offset = 0x0000; - - if (phy->rev == 1) - offset = 0x4C00; - - bcm43xx_ilt_write(bcm, offset, 0x00FE); - bcm43xx_ilt_write(bcm, offset + 1, 0x000D); - bcm43xx_ilt_write(bcm, offset + 2, 0x0013); - bcm43xx_ilt_write(bcm, offset + 3, 0x0019); - - if (phy->rev == 1) { - bcm43xx_ilt_write(bcm, 0x1800, 0x2710); - bcm43xx_ilt_write(bcm, 0x1801, 0x9B83); - bcm43xx_ilt_write(bcm, 0x1802, 0x9B83); - bcm43xx_ilt_write(bcm, 0x1803, 0x0F8D); - bcm43xx_phy_write(bcm, 0x0455, 0x0004); - } - - bcm43xx_phy_write(bcm, 0x04A5, (bcm43xx_phy_read(bcm, 0x04A5) & 0x00FF) | 0x5700); - bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xFF80) | 0x000F); - bcm43xx_phy_write(bcm, 0x041A, (bcm43xx_phy_read(bcm, 0x041A) & 0xC07F) | 0x2B80); - bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) & 0xF0FF) | 0x0300); - - bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0008); - - bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xFFF0) | 0x0008); - bcm43xx_phy_write(bcm, 0x04A1, (bcm43xx_phy_read(bcm, 0x04A1) & 0xF0FF) | 0x0600); - bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xF0FF) | 0x0700); - bcm43xx_phy_write(bcm, 0x04A0, (bcm43xx_phy_read(bcm, 0x04A0) & 0xF0FF) | 0x0100); - - if (phy->rev == 1) - bcm43xx_phy_write(bcm, 0x04A2, (bcm43xx_phy_read(bcm, 0x04A2) & 0xFFF0) | 0x0007); - - bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xFF00) | 0x001C); - bcm43xx_phy_write(bcm, 0x0488, (bcm43xx_phy_read(bcm, 0x0488) & 0xC0FF) | 0x0200); - bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0xFF00) | 0x001C); - bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xFF00) | 0x0020); - bcm43xx_phy_write(bcm, 0x0489, (bcm43xx_phy_read(bcm, 0x0489) & 0xC0FF) | 0x0200); - bcm43xx_phy_write(bcm, 0x0482, (bcm43xx_phy_read(bcm, 0x0482) & 0xFF00) | 0x002E); - bcm43xx_phy_write(bcm, 0x0496, (bcm43xx_phy_read(bcm, 0x0496) & 0x00FF) | 0x1A00); - bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0xFF00) | 0x0028); - bcm43xx_phy_write(bcm, 0x0481, (bcm43xx_phy_read(bcm, 0x0481) & 0x00FF) | 0x2C00); - - if (phy->rev == 1) { - bcm43xx_phy_write(bcm, 0x0430, 0x092B); - bcm43xx_phy_write(bcm, 0x041B, (bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1) | 0x0002); - } else { - bcm43xx_phy_write(bcm, 0x041B, bcm43xx_phy_read(bcm, 0x041B) & 0xFFE1); - bcm43xx_phy_write(bcm, 0x041F, 0x287A); - bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) & 0xFFF0) | 0x0004); - } - - if (phy->rev > 2) { - bcm43xx_phy_write(bcm, 0x0422, 0x287A); - bcm43xx_phy_write(bcm, 0x0420, (bcm43xx_phy_read(bcm, 0x0420) - & 0x0FFF) | 0x3000); - } - - bcm43xx_phy_write(bcm, 0x04A8, (bcm43xx_phy_read(bcm, 0x04A8) & 0x8080) - | 0x7874); - bcm43xx_phy_write(bcm, 0x048E, 0x1C00); - - if (phy->rev == 1) { - bcm43xx_phy_write(bcm, 0x04AB, (bcm43xx_phy_read(bcm, 0x04AB) - & 0xF0FF) | 0x0600); - bcm43xx_phy_write(bcm, 0x048B, 0x005E); - bcm43xx_phy_write(bcm, 0x048C, (bcm43xx_phy_read(bcm, 0x048C) - & 0xFF00) | 0x001E); - bcm43xx_phy_write(bcm, 0x048D, 0x0002); - } - - bcm43xx_ilt_write(bcm, offset + 0x0800, 0); - bcm43xx_ilt_write(bcm, offset + 0x0801, 7); - bcm43xx_ilt_write(bcm, offset + 0x0802, 16); - bcm43xx_ilt_write(bcm, offset + 0x0803, 28); - - if (phy->rev >= 6) { - bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426) - & 0xFFFC)); - bcm43xx_phy_write(bcm, 0x0426, (bcm43xx_phy_read(bcm, 0x0426) - & 0xEFFF)); - } -} - -static void bcm43xx_phy_setupg(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 i; - - assert(phy->type == BCM43xx_PHYTYPE_G); - if (phy->rev == 1) { - bcm43xx_phy_write(bcm, 0x0406, 0x4F19); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) - & 0xFC3F) | 0x0340); - bcm43xx_phy_write(bcm, 0x042C, 0x005A); - bcm43xx_phy_write(bcm, 0x0427, 0x001A); - - for (i = 0; i < BCM43xx_ILT_FINEFREQG_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqg[i]); - for (i = 0; i < BCM43xx_ILT_NOISEG1_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg1[i]); - for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); - } else { - /* nrssi values are signed 6-bit values. Not sure why we write 0x7654 here... */ - bcm43xx_nrssi_hw_write(bcm, 0xBA98, (s16)0x7654); - - if (phy->rev == 2) { - bcm43xx_phy_write(bcm, 0x04C0, 0x1861); - bcm43xx_phy_write(bcm, 0x04C1, 0x0271); - } else if (phy->rev > 2) { - bcm43xx_phy_write(bcm, 0x04C0, 0x0098); - bcm43xx_phy_write(bcm, 0x04C1, 0x0070); - bcm43xx_phy_write(bcm, 0x04C9, 0x0080); - } - bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x800); - - for (i = 0; i < 64; i++) - bcm43xx_ilt_write(bcm, 0x4000 + i, i); - for (i = 0; i < BCM43xx_ILT_NOISEG2_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noiseg2[i]); - } - - if (phy->rev <= 2) - for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg1[i]); - else if ((phy->rev >= 7) && (bcm43xx_phy_read(bcm, 0x0449) & 0x0200)) - for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg3[i]); - else - for (i = 0; i < BCM43xx_ILT_NOISESCALEG_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1400 + i, bcm43xx_ilt_noisescaleg2[i]); - - if (phy->rev == 2) - for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); - else if ((phy->rev > 2) && (phy->rev <= 8)) - for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr2[i]); - - if (phy->rev == 1) { - for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); - for (i = 0; i < 4; i++) { - bcm43xx_ilt_write(bcm, 0x5404 + i, 0x0020); - bcm43xx_ilt_write(bcm, 0x5408 + i, 0x0020); - bcm43xx_ilt_write(bcm, 0x540C + i, 0x0020); - bcm43xx_ilt_write(bcm, 0x5410 + i, 0x0020); - } - bcm43xx_phy_agcsetup(bcm); - - if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type == 0x0416) && - (bcm->board_revision == 0x0017)) - return; - - bcm43xx_ilt_write(bcm, 0x5001, 0x0002); - bcm43xx_ilt_write(bcm, 0x5002, 0x0001); - } else { - for (i = 0; i <= 0x2F; i++) - bcm43xx_ilt_write(bcm, 0x1000 + i, 0x0820); - bcm43xx_phy_agcsetup(bcm); - bcm43xx_phy_read(bcm, 0x0400); /* dummy read */ - bcm43xx_phy_write(bcm, 0x0403, 0x1000); - bcm43xx_ilt_write(bcm, 0x3C02, 0x000F); - bcm43xx_ilt_write(bcm, 0x3C03, 0x0014); - - if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type == 0x0416) && - (bcm->board_revision == 0x0017)) - return; - - bcm43xx_ilt_write(bcm, 0x0401, 0x0002); - bcm43xx_ilt_write(bcm, 0x0402, 0x0001); - } -} - -/* Initialize the noisescaletable for APHY */ -static void bcm43xx_phy_init_noisescaletbl(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - int i; - - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_CTRL, 0x1400); - for (i = 0; i < 12; i++) { - if (phy->rev == 2) - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767); - else - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323); - } - if (phy->rev == 2) - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6700); - else - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2300); - for (i = 0; i < 11; i++) { - if (phy->rev == 2) - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x6767); - else - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x2323); - } - if (phy->rev == 2) - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0067); - else - bcm43xx_phy_write(bcm, BCM43xx_PHY_ILT_A_DATA1, 0x0023); -} - -static void bcm43xx_phy_setupa(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 i; - - assert(phy->type == BCM43xx_PHYTYPE_A); - switch (phy->rev) { - case 2: - bcm43xx_phy_write(bcm, 0x008E, 0x3800); - bcm43xx_phy_write(bcm, 0x0035, 0x03FF); - bcm43xx_phy_write(bcm, 0x0036, 0x0400); - - bcm43xx_ilt_write(bcm, 0x3807, 0x0051); - - bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); - bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); - bcm43xx_ilt_write(bcm, 0x3C0C, 0x07BF); - bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); - - bcm43xx_phy_write(bcm, 0x0024, 0x4680); - bcm43xx_phy_write(bcm, 0x0020, 0x0003); - bcm43xx_phy_write(bcm, 0x001D, 0x0F40); - bcm43xx_phy_write(bcm, 0x001F, 0x1C00); - - bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); - bcm43xx_phy_write(bcm, 0x002B, bcm43xx_phy_read(bcm, 0x002B) & 0xFBFF); - bcm43xx_phy_write(bcm, 0x008E, 0x58C1); - - bcm43xx_ilt_write(bcm, 0x0803, 0x000F); - bcm43xx_ilt_write(bcm, 0x0804, 0x001F); - bcm43xx_ilt_write(bcm, 0x0805, 0x002A); - bcm43xx_ilt_write(bcm, 0x0805, 0x0030); - bcm43xx_ilt_write(bcm, 0x0807, 0x003A); - - bcm43xx_ilt_write(bcm, 0x0000, 0x0013); - bcm43xx_ilt_write(bcm, 0x0001, 0x0013); - bcm43xx_ilt_write(bcm, 0x0002, 0x0013); - bcm43xx_ilt_write(bcm, 0x0003, 0x0013); - bcm43xx_ilt_write(bcm, 0x0004, 0x0015); - bcm43xx_ilt_write(bcm, 0x0005, 0x0015); - bcm43xx_ilt_write(bcm, 0x0006, 0x0019); - - bcm43xx_ilt_write(bcm, 0x0404, 0x0003); - bcm43xx_ilt_write(bcm, 0x0405, 0x0003); - bcm43xx_ilt_write(bcm, 0x0406, 0x0007); - - for (i = 0; i < 16; i++) - bcm43xx_ilt_write(bcm, 0x4000 + i, (0x8 + i) & 0x000F); - - bcm43xx_ilt_write(bcm, 0x3003, 0x1044); - bcm43xx_ilt_write(bcm, 0x3004, 0x7201); - bcm43xx_ilt_write(bcm, 0x3006, 0x0040); - bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008); - - for (i = 0; i < BCM43xx_ILT_FINEFREQA_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5800 + i, bcm43xx_ilt_finefreqa[i]); - for (i = 0; i < BCM43xx_ILT_NOISEA2_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea2[i]); - for (i = 0; i < BCM43xx_ILT_ROTOR_SIZE; i++) - bcm43xx_ilt_write32(bcm, 0x2000 + i, bcm43xx_ilt_rotor[i]); - bcm43xx_phy_init_noisescaletbl(bcm); - for (i = 0; i < BCM43xx_ILT_RETARD_SIZE; i++) - bcm43xx_ilt_write32(bcm, 0x2400 + i, bcm43xx_ilt_retard[i]); - break; - case 3: - for (i = 0; i < 64; i++) - bcm43xx_ilt_write(bcm, 0x4000 + i, i); - - bcm43xx_ilt_write(bcm, 0x3807, 0x0051); - - bcm43xx_phy_write(bcm, 0x001C, 0x0FF9); - bcm43xx_phy_write(bcm, 0x0020, bcm43xx_phy_read(bcm, 0x0020) & 0xFF0F); - bcm43xx_radio_write16(bcm, 0x0002, 0x07BF); - - bcm43xx_phy_write(bcm, 0x0024, 0x4680); - bcm43xx_phy_write(bcm, 0x0020, 0x0003); - bcm43xx_phy_write(bcm, 0x001D, 0x0F40); - bcm43xx_phy_write(bcm, 0x001F, 0x1C00); - bcm43xx_phy_write(bcm, 0x002A, (bcm43xx_phy_read(bcm, 0x002A) & 0x00FF) | 0x0400); - - bcm43xx_ilt_write(bcm, 0x3001, (bcm43xx_ilt_read(bcm, 0x3001) & 0x0010) | 0x0008); - for (i = 0; i < BCM43xx_ILT_NOISEA3_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x1800 + i, bcm43xx_ilt_noisea3[i]); - bcm43xx_phy_init_noisescaletbl(bcm); - for (i = 0; i < BCM43xx_ILT_SIGMASQR_SIZE; i++) - bcm43xx_ilt_write(bcm, 0x5000 + i, bcm43xx_ilt_sigmasqr1[i]); - - bcm43xx_phy_write(bcm, 0x0003, 0x1808); - - bcm43xx_ilt_write(bcm, 0x0803, 0x000F); - bcm43xx_ilt_write(bcm, 0x0804, 0x001F); - bcm43xx_ilt_write(bcm, 0x0805, 0x002A); - bcm43xx_ilt_write(bcm, 0x0805, 0x0030); - bcm43xx_ilt_write(bcm, 0x0807, 0x003A); - - bcm43xx_ilt_write(bcm, 0x0000, 0x0013); - bcm43xx_ilt_write(bcm, 0x0001, 0x0013); - bcm43xx_ilt_write(bcm, 0x0002, 0x0013); - bcm43xx_ilt_write(bcm, 0x0003, 0x0013); - bcm43xx_ilt_write(bcm, 0x0004, 0x0015); - bcm43xx_ilt_write(bcm, 0x0005, 0x0015); - bcm43xx_ilt_write(bcm, 0x0006, 0x0019); - - bcm43xx_ilt_write(bcm, 0x0404, 0x0003); - bcm43xx_ilt_write(bcm, 0x0405, 0x0003); - bcm43xx_ilt_write(bcm, 0x0406, 0x0007); - - bcm43xx_ilt_write(bcm, 0x3C02, 0x000F); - bcm43xx_ilt_write(bcm, 0x3C03, 0x0014); - break; - default: - assert(0); - } -} - -/* Initialize APHY. This is also called for the GPHY in some cases. */ -static void bcm43xx_phy_inita(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 tval; - - if (phy->type == BCM43xx_PHYTYPE_A) { - bcm43xx_phy_setupa(bcm); - } else { - bcm43xx_phy_setupg(bcm); - if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) - bcm43xx_phy_write(bcm, 0x046E, 0x03CF); - return; - } - - bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) & 0xF83C) | 0x0340); - bcm43xx_phy_write(bcm, 0x0034, 0x0001); - - TODO();//TODO: RSSI AGC - bcm43xx_phy_write(bcm, BCM43xx_PHY_A_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_A_CRS) | (1 << 14)); - bcm43xx_radio_init2060(bcm); - - if ((bcm->board_vendor == PCI_VENDOR_ID_BROADCOM) - && ((bcm->board_type == 0x0416) || (bcm->board_type == 0x040A))) { - if (radio->lofcal == 0xFFFF) { - TODO();//TODO: LOF Cal - bcm43xx_radio_set_tx_iq(bcm); - } else - bcm43xx_radio_write16(bcm, 0x001E, radio->lofcal); - } - - bcm43xx_phy_write(bcm, 0x007A, 0xF111); - - if (phy->savedpctlreg == 0xFFFF) { - bcm43xx_radio_write16(bcm, 0x0019, 0x0000); - bcm43xx_radio_write16(bcm, 0x0017, 0x0020); - - tval = bcm43xx_ilt_read(bcm, 0x3001); - if (phy->rev == 1) { - bcm43xx_ilt_write(bcm, 0x3001, - (bcm43xx_ilt_read(bcm, 0x3001) & 0xFF87) - | 0x0058); - } else { - bcm43xx_ilt_write(bcm, 0x3001, - (bcm43xx_ilt_read(bcm, 0x3001) & 0xFFC3) - | 0x002C); - } - bcm43xx_dummy_transmission(bcm); - phy->savedpctlreg = bcm43xx_phy_read(bcm, BCM43xx_PHY_A_PCTL); - bcm43xx_ilt_write(bcm, 0x3001, tval); - - bcm43xx_radio_set_txpower_a(bcm, 0x0018); - } - bcm43xx_radio_clear_tssi(bcm); -} - -static void bcm43xx_phy_initb2(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 offset, val; - - bcm43xx_write16(bcm, 0x03EC, 0x3F22); - bcm43xx_phy_write(bcm, 0x0020, 0x301C); - bcm43xx_phy_write(bcm, 0x0026, 0x0000); - bcm43xx_phy_write(bcm, 0x0030, 0x00C6); - bcm43xx_phy_write(bcm, 0x0088, 0x3E00); - val = 0x3C3D; - for (offset = 0x0089; offset < 0x00A7; offset++) { - bcm43xx_phy_write(bcm, offset, val); - val -= 0x0202; - } - bcm43xx_phy_write(bcm, 0x03E4, 0x3000); - if (radio->channel == 0xFF) - bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); - else - bcm43xx_radio_selectchannel(bcm, radio->channel, 0); - if (radio->version != 0x2050) { - bcm43xx_radio_write16(bcm, 0x0075, 0x0080); - bcm43xx_radio_write16(bcm, 0x0079, 0x0081); - } - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x0050, 0x0023); - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x005A, 0x0070); - bcm43xx_radio_write16(bcm, 0x005B, 0x007B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); - bcm43xx_radio_write16(bcm, 0x007A, 0x000F); - bcm43xx_phy_write(bcm, 0x0038, 0x0677); - bcm43xx_radio_init2050(bcm); - } - bcm43xx_phy_write(bcm, 0x0014, 0x0080); - bcm43xx_phy_write(bcm, 0x0032, 0x00CA); - bcm43xx_phy_write(bcm, 0x0032, 0x00CC); - bcm43xx_phy_write(bcm, 0x0035, 0x07C2); - bcm43xx_phy_lo_b_measure(bcm); - bcm43xx_phy_write(bcm, 0x0026, 0xCC00); - if (radio->version != 0x2050) - bcm43xx_phy_write(bcm, 0x0026, 0xCE00); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1000); - bcm43xx_phy_write(bcm, 0x002A, 0x88A3); - if (radio->version != 0x2050) - bcm43xx_phy_write(bcm, 0x002A, 0x88C2); - bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - bcm43xx_phy_init_pctl(bcm); -} - -static void bcm43xx_phy_initb4(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 offset, val; - - bcm43xx_write16(bcm, 0x03EC, 0x3F22); - bcm43xx_phy_write(bcm, 0x0020, 0x301C); - bcm43xx_phy_write(bcm, 0x0026, 0x0000); - bcm43xx_phy_write(bcm, 0x0030, 0x00C6); - bcm43xx_phy_write(bcm, 0x0088, 0x3E00); - val = 0x3C3D; - for (offset = 0x0089; offset < 0x00A7; offset++) { - bcm43xx_phy_write(bcm, offset, val); - val -= 0x0202; - } - bcm43xx_phy_write(bcm, 0x03E4, 0x3000); - if (radio->channel == 0xFF) - bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 0); - else - bcm43xx_radio_selectchannel(bcm, radio->channel, 0); - if (radio->version != 0x2050) { - bcm43xx_radio_write16(bcm, 0x0075, 0x0080); - bcm43xx_radio_write16(bcm, 0x0079, 0x0081); - } - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x0050, 0x0023); - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x005A, 0x0070); - bcm43xx_radio_write16(bcm, 0x005B, 0x007B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); - bcm43xx_radio_write16(bcm, 0x007A, 0x000F); - bcm43xx_phy_write(bcm, 0x0038, 0x0677); - bcm43xx_radio_init2050(bcm); - } - bcm43xx_phy_write(bcm, 0x0014, 0x0080); - bcm43xx_phy_write(bcm, 0x0032, 0x00CA); - if (radio->version == 0x2050) - bcm43xx_phy_write(bcm, 0x0032, 0x00E0); - bcm43xx_phy_write(bcm, 0x0035, 0x07C2); - - bcm43xx_phy_lo_b_measure(bcm); - - bcm43xx_phy_write(bcm, 0x0026, 0xCC00); - if (radio->version == 0x2050) - bcm43xx_phy_write(bcm, 0x0026, 0xCE00); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x1100); - bcm43xx_phy_write(bcm, 0x002A, 0x88A3); - if (radio->version == 0x2050) - bcm43xx_phy_write(bcm, 0x002A, 0x88C2); - bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - bcm43xx_calc_nrssi_slope(bcm); - bcm43xx_calc_nrssi_threshold(bcm); - } - bcm43xx_phy_init_pctl(bcm); -} - -static void bcm43xx_phy_initb5(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 offset; - u16 value; - u8 old_channel; - - if (phy->analog == 1) - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) - | 0x0050); - if ((bcm->board_vendor != PCI_VENDOR_ID_BROADCOM) && - (bcm->board_type != 0x0416)) { - value = 0x2120; - for (offset = 0x00A8 ; offset < 0x00C7; offset++) { - bcm43xx_phy_write(bcm, offset, value); - value += 0x0202; - } - } - bcm43xx_phy_write(bcm, 0x0035, - (bcm43xx_phy_read(bcm, 0x0035) & 0xF0FF) - | 0x0700); - if (radio->version == 0x2050) - bcm43xx_phy_write(bcm, 0x0038, 0x0667); - - if (phy->connected) { - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) - | 0x0020); - bcm43xx_radio_write16(bcm, 0x0051, - bcm43xx_radio_read16(bcm, 0x0051) - | 0x0004); - } - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, 0x0000); - - bcm43xx_phy_write(bcm, 0x0802, bcm43xx_phy_read(bcm, 0x0802) | 0x0100); - bcm43xx_phy_write(bcm, 0x042B, bcm43xx_phy_read(bcm, 0x042B) | 0x2000); - - bcm43xx_phy_write(bcm, 0x001C, 0x186A); - - bcm43xx_phy_write(bcm, 0x0013, (bcm43xx_phy_read(bcm, 0x0013) & 0x00FF) | 0x1900); - bcm43xx_phy_write(bcm, 0x0035, (bcm43xx_phy_read(bcm, 0x0035) & 0xFFC0) | 0x0064); - bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) & 0xFF80) | 0x000A); - } - - if (bcm->bad_frames_preempt) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | (1 << 11)); - } - - if (phy->analog == 1) { - bcm43xx_phy_write(bcm, 0x0026, 0xCE00); - bcm43xx_phy_write(bcm, 0x0021, 0x3763); - bcm43xx_phy_write(bcm, 0x0022, 0x1BC3); - bcm43xx_phy_write(bcm, 0x0023, 0x06F9); - bcm43xx_phy_write(bcm, 0x0024, 0x037E); - } else - bcm43xx_phy_write(bcm, 0x0026, 0xCC00); - bcm43xx_phy_write(bcm, 0x0030, 0x00C6); - bcm43xx_write16(bcm, 0x03EC, 0x3F22); - - if (phy->analog == 1) - bcm43xx_phy_write(bcm, 0x0020, 0x3E1C); - else - bcm43xx_phy_write(bcm, 0x0020, 0x301C); - - if (phy->analog == 0) - bcm43xx_write16(bcm, 0x03E4, 0x3000); - - old_channel = radio->channel; - /* Force to channel 7, even if not supported. */ - bcm43xx_radio_selectchannel(bcm, 7, 0); - - if (radio->version != 0x2050) { - bcm43xx_radio_write16(bcm, 0x0075, 0x0080); - bcm43xx_radio_write16(bcm, 0x0079, 0x0081); - } - - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x0050, 0x0023); - - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x005A, 0x0070); - } - - bcm43xx_radio_write16(bcm, 0x005B, 0x007B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); - - bcm43xx_radio_write16(bcm, 0x007A, bcm43xx_radio_read16(bcm, 0x007A) | 0x0007); - - bcm43xx_radio_selectchannel(bcm, old_channel, 0); - - bcm43xx_phy_write(bcm, 0x0014, 0x0080); - bcm43xx_phy_write(bcm, 0x0032, 0x00CA); - bcm43xx_phy_write(bcm, 0x002A, 0x88A3); - - bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - - if (radio->version == 0x2050) - bcm43xx_radio_write16(bcm, 0x005D, 0x000D); - - bcm43xx_write16(bcm, 0x03E4, (bcm43xx_read16(bcm, 0x03E4) & 0xFFC0) | 0x0004); -} - -static void bcm43xx_phy_initb6(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 offset, val; - u8 old_channel; - - bcm43xx_phy_write(bcm, 0x003E, 0x817A); - bcm43xx_radio_write16(bcm, 0x007A, - (bcm43xx_radio_read16(bcm, 0x007A) | 0x0058)); - if (radio->revision == 4 || - radio->revision == 5) { - bcm43xx_radio_write16(bcm, 0x0051, 0x0037); - bcm43xx_radio_write16(bcm, 0x0052, 0x0070); - bcm43xx_radio_write16(bcm, 0x0053, 0x00B3); - bcm43xx_radio_write16(bcm, 0x0054, 0x009B); - bcm43xx_radio_write16(bcm, 0x005A, 0x0088); - bcm43xx_radio_write16(bcm, 0x005B, 0x0088); - bcm43xx_radio_write16(bcm, 0x005D, 0x0088); - bcm43xx_radio_write16(bcm, 0x005E, 0x0088); - bcm43xx_radio_write16(bcm, 0x007D, 0x0088); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET) - | 0x00000200)); - } - if (radio->revision == 8) { - bcm43xx_radio_write16(bcm, 0x0051, 0x0000); - bcm43xx_radio_write16(bcm, 0x0052, 0x0040); - bcm43xx_radio_write16(bcm, 0x0053, 0x00B7); - bcm43xx_radio_write16(bcm, 0x0054, 0x0098); - bcm43xx_radio_write16(bcm, 0x005A, 0x0088); - bcm43xx_radio_write16(bcm, 0x005B, 0x006B); - bcm43xx_radio_write16(bcm, 0x005C, 0x000F); - if (bcm->sprom.boardflags & 0x8000) { - bcm43xx_radio_write16(bcm, 0x005D, 0x00FA); - bcm43xx_radio_write16(bcm, 0x005E, 0x00D8); - } else { - bcm43xx_radio_write16(bcm, 0x005D, 0x00F5); - bcm43xx_radio_write16(bcm, 0x005E, 0x00B8); - } - bcm43xx_radio_write16(bcm, 0x0073, 0x0003); - bcm43xx_radio_write16(bcm, 0x007D, 0x00A8); - bcm43xx_radio_write16(bcm, 0x007C, 0x0001); - bcm43xx_radio_write16(bcm, 0x007E, 0x0008); - } - val = 0x1E1F; - for (offset = 0x0088; offset < 0x0098; offset++) { - bcm43xx_phy_write(bcm, offset, val); - val -= 0x0202; - } - val = 0x3E3F; - for (offset = 0x0098; offset < 0x00A8; offset++) { - bcm43xx_phy_write(bcm, offset, val); - val -= 0x0202; - } - val = 0x2120; - for (offset = 0x00A8; offset < 0x00C8; offset++) { - bcm43xx_phy_write(bcm, offset, (val & 0x3F3F)); - val += 0x0202; - } - if (phy->type == BCM43xx_PHYTYPE_G) { - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0020); - bcm43xx_radio_write16(bcm, 0x0051, - bcm43xx_radio_read16(bcm, 0x0051) | 0x0004); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) | 0x0100); - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) | 0x2000); - bcm43xx_phy_write(bcm, 0x5B, 0x0000); - bcm43xx_phy_write(bcm, 0x5C, 0x0000); - } - - old_channel = radio->channel; - if (old_channel >= 8) - bcm43xx_radio_selectchannel(bcm, 1, 0); - else - bcm43xx_radio_selectchannel(bcm, 13, 0); - - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - bcm43xx_radio_write16(bcm, 0x0050, 0x0023); - udelay(40); - if (radio->revision < 6 || radio-> revision == 8) { - bcm43xx_radio_write16(bcm, 0x007C, (bcm43xx_radio_read16(bcm, 0x007C) - | 0x0002)); - bcm43xx_radio_write16(bcm, 0x0050, 0x0020); - } - if (radio->revision <= 2) { - bcm43xx_radio_write16(bcm, 0x007C, 0x0020); - bcm43xx_radio_write16(bcm, 0x005A, 0x0070); - bcm43xx_radio_write16(bcm, 0x005B, 0x007B); - bcm43xx_radio_write16(bcm, 0x005C, 0x00B0); - } - bcm43xx_radio_write16(bcm, 0x007A, - (bcm43xx_radio_read16(bcm, 0x007A) & 0x00F8) | 0x0007); - - bcm43xx_radio_selectchannel(bcm, old_channel, 0); - - bcm43xx_phy_write(bcm, 0x0014, 0x0200); - if (radio->revision >= 6) - bcm43xx_phy_write(bcm, 0x002A, 0x88C2); - else - bcm43xx_phy_write(bcm, 0x002A, 0x8AC0); - bcm43xx_phy_write(bcm, 0x0038, 0x0668); - bcm43xx_radio_set_txpower_bg(bcm, 0xFFFF, 0xFFFF, 0xFFFF); - if (radio->revision <= 5) - bcm43xx_phy_write(bcm, 0x005D, (bcm43xx_phy_read(bcm, 0x005D) - & 0xFF80) | 0x0003); - if (radio->revision <= 2) - bcm43xx_radio_write16(bcm, 0x005D, 0x000D); - - if (phy->analog == 4){ - bcm43xx_write16(bcm, 0x03E4, 0x0009); - bcm43xx_phy_write(bcm, 0x61, bcm43xx_phy_read(bcm, 0x61) & 0xFFF); - } else { - bcm43xx_phy_write(bcm, 0x0002, (bcm43xx_phy_read(bcm, 0x0002) & 0xFFC0) | 0x0004); - } - if (phy->type == BCM43xx_PHYTYPE_G) - bcm43xx_write16(bcm, 0x03E6, 0x0); - if (phy->type == BCM43xx_PHYTYPE_B) { - bcm43xx_write16(bcm, 0x03E6, 0x8140); - bcm43xx_phy_write(bcm, 0x0016, 0x0410); - bcm43xx_phy_write(bcm, 0x0017, 0x0820); - bcm43xx_phy_write(bcm, 0x0062, 0x0007); - bcm43xx_radio_init2050(bcm); - bcm43xx_phy_lo_g_measure(bcm); - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - bcm43xx_calc_nrssi_slope(bcm); - bcm43xx_calc_nrssi_threshold(bcm); - } - bcm43xx_phy_init_pctl(bcm); - } -} - -static void bcm43xx_calc_loopback_gain(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup_phy[15] = {0}; - u16 backup_radio[3]; - u16 backup_bband; - u16 i; - u16 loop1_cnt, loop1_done, loop1_omitted; - u16 loop2_done; - - backup_phy[0] = bcm43xx_phy_read(bcm, 0x0429); - backup_phy[1] = bcm43xx_phy_read(bcm, 0x0001); - backup_phy[2] = bcm43xx_phy_read(bcm, 0x0811); - backup_phy[3] = bcm43xx_phy_read(bcm, 0x0812); - if (phy->rev != 1) { - backup_phy[4] = bcm43xx_phy_read(bcm, 0x0814); - backup_phy[5] = bcm43xx_phy_read(bcm, 0x0815); - } - backup_phy[6] = bcm43xx_phy_read(bcm, 0x005A); - backup_phy[7] = bcm43xx_phy_read(bcm, 0x0059); - backup_phy[8] = bcm43xx_phy_read(bcm, 0x0058); - backup_phy[9] = bcm43xx_phy_read(bcm, 0x000A); - backup_phy[10] = bcm43xx_phy_read(bcm, 0x0003); - backup_phy[11] = bcm43xx_phy_read(bcm, 0x080F); - backup_phy[12] = bcm43xx_phy_read(bcm, 0x0810); - backup_phy[13] = bcm43xx_phy_read(bcm, 0x002B); - backup_phy[14] = bcm43xx_phy_read(bcm, 0x0015); - bcm43xx_phy_read(bcm, 0x002D); /* dummy read */ - backup_bband = radio->baseband_atten; - backup_radio[0] = bcm43xx_radio_read16(bcm, 0x0052); - backup_radio[1] = bcm43xx_radio_read16(bcm, 0x0043); - backup_radio[2] = bcm43xx_radio_read16(bcm, 0x007A); - - bcm43xx_phy_write(bcm, 0x0429, - bcm43xx_phy_read(bcm, 0x0429) & 0x3FFF); - bcm43xx_phy_write(bcm, 0x0001, - bcm43xx_phy_read(bcm, 0x0001) & 0x8000); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x0002); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) & 0xFFFD); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x0001); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) & 0xFFFE); - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0001); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0002); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFD); - } - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x000C); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) | 0x000C); - - bcm43xx_phy_write(bcm, 0x0811, - (bcm43xx_phy_read(bcm, 0x0811) - & 0xFFCF) | 0x0030); - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) - & 0xFFCF) | 0x0010); - - bcm43xx_phy_write(bcm, 0x005A, 0x0780); - bcm43xx_phy_write(bcm, 0x0059, 0xC810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->analog == 0) { - bcm43xx_phy_write(bcm, 0x0003, 0x0122); - } else { - bcm43xx_phy_write(bcm, 0x000A, - bcm43xx_phy_read(bcm, 0x000A) - | 0x2000); - } - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0004); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); - } - bcm43xx_phy_write(bcm, 0x0003, - (bcm43xx_phy_read(bcm, 0x0003) - & 0xFF9F) | 0x0040); - if (radio->version == 0x2050 && radio->revision == 2) { - bcm43xx_radio_write16(bcm, 0x0052, 0x0000); - bcm43xx_radio_write16(bcm, 0x0043, - (bcm43xx_radio_read16(bcm, 0x0043) - & 0xFFF0) | 0x0009); - loop1_cnt = 9; - } else if (radio->revision == 8) { - bcm43xx_radio_write16(bcm, 0x0043, 0x000F); - loop1_cnt = 15; - } else - loop1_cnt = 0; - - bcm43xx_phy_set_baseband_attenuation(bcm, 11); - - if (phy->rev >= 3) - bcm43xx_phy_write(bcm, 0x080F, 0xC020); - else - bcm43xx_phy_write(bcm, 0x080F, 0x8020); - bcm43xx_phy_write(bcm, 0x0810, 0x0000); - - bcm43xx_phy_write(bcm, 0x002B, - (bcm43xx_phy_read(bcm, 0x002B) - & 0xFFC0) | 0x0001); - bcm43xx_phy_write(bcm, 0x002B, - (bcm43xx_phy_read(bcm, 0x002B) - & 0xC0FF) | 0x0800); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x0100); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) & 0xCFFF); - if (bcm->sprom.boardflags & BCM43xx_BFL_EXTLNA) { - if (phy->rev >= 7) { - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) - | 0x0800); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) - | 0x8000); - } - } - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) - & 0x00F7); - - for (i = 0; i < loop1_cnt; i++) { - bcm43xx_radio_write16(bcm, 0x0043, loop1_cnt); - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) - & 0xF0FF) | (i << 8)); - bcm43xx_phy_write(bcm, 0x0015, - (bcm43xx_phy_read(bcm, 0x0015) - & 0x0FFF) | 0xA000); - bcm43xx_phy_write(bcm, 0x0015, - (bcm43xx_phy_read(bcm, 0x0015) - & 0x0FFF) | 0xF000); - udelay(20); - if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC) - break; - } - loop1_done = i; - loop1_omitted = loop1_cnt - loop1_done; - - loop2_done = 0; - if (loop1_done >= 8) { - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) - | 0x0030); - for (i = loop1_done - 8; i < 16; i++) { - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) - & 0xF0FF) | (i << 8)); - bcm43xx_phy_write(bcm, 0x0015, - (bcm43xx_phy_read(bcm, 0x0015) - & 0x0FFF) | 0xA000); - bcm43xx_phy_write(bcm, 0x0015, - (bcm43xx_phy_read(bcm, 0x0015) - & 0x0FFF) | 0xF000); - udelay(20); - if (bcm43xx_phy_read(bcm, 0x002D) >= 0x0DFC) - break; - } - } - - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x0814, backup_phy[4]); - bcm43xx_phy_write(bcm, 0x0815, backup_phy[5]); - } - bcm43xx_phy_write(bcm, 0x005A, backup_phy[6]); - bcm43xx_phy_write(bcm, 0x0059, backup_phy[7]); - bcm43xx_phy_write(bcm, 0x0058, backup_phy[8]); - bcm43xx_phy_write(bcm, 0x000A, backup_phy[9]); - bcm43xx_phy_write(bcm, 0x0003, backup_phy[10]); - bcm43xx_phy_write(bcm, 0x080F, backup_phy[11]); - bcm43xx_phy_write(bcm, 0x0810, backup_phy[12]); - bcm43xx_phy_write(bcm, 0x002B, backup_phy[13]); - bcm43xx_phy_write(bcm, 0x0015, backup_phy[14]); - - bcm43xx_phy_set_baseband_attenuation(bcm, backup_bband); - - bcm43xx_radio_write16(bcm, 0x0052, backup_radio[0]); - bcm43xx_radio_write16(bcm, 0x0043, backup_radio[1]); - bcm43xx_radio_write16(bcm, 0x007A, backup_radio[2]); - - bcm43xx_phy_write(bcm, 0x0811, backup_phy[2] | 0x0003); - udelay(10); - bcm43xx_phy_write(bcm, 0x0811, backup_phy[2]); - bcm43xx_phy_write(bcm, 0x0812, backup_phy[3]); - bcm43xx_phy_write(bcm, 0x0429, backup_phy[0]); - bcm43xx_phy_write(bcm, 0x0001, backup_phy[1]); - - phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11; - phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2; -} - -static void bcm43xx_phy_initg(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 tmp; - - if (phy->rev == 1) - bcm43xx_phy_initb5(bcm); - else - bcm43xx_phy_initb6(bcm); - if (phy->rev >= 2 || phy->connected) - bcm43xx_phy_inita(bcm); - - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0814, 0x0000); - bcm43xx_phy_write(bcm, 0x0815, 0x0000); - } - if (phy->rev == 2) { - bcm43xx_phy_write(bcm, 0x0811, 0x0000); - bcm43xx_phy_write(bcm, 0x0015, 0x00C0); - } - if (phy->rev > 5) { - bcm43xx_phy_write(bcm, 0x0811, 0x0400); - bcm43xx_phy_write(bcm, 0x0015, 0x00C0); - } - if (phy->rev >= 2 && phy->connected) { - tmp = bcm43xx_phy_read(bcm, 0x0400) & 0xFF; - if (tmp ==3 || tmp == 5) { - bcm43xx_phy_write(bcm, 0x04C2, 0x1816); - bcm43xx_phy_write(bcm, 0x04C3, 0x8006); - if (tmp == 5) { - bcm43xx_phy_write(bcm, 0x04CC, - (bcm43xx_phy_read(bcm, 0x04CC) - & 0x00FF) | 0x1F00); - } - } - bcm43xx_phy_write(bcm, 0x047E, 0x0078); - } - if (radio->revision == 8) { - bcm43xx_phy_write(bcm, 0x0801, bcm43xx_phy_read(bcm, 0x0801) | 0x0080); - bcm43xx_phy_write(bcm, 0x043E, bcm43xx_phy_read(bcm, 0x043E) | 0x0004); - } - if (phy->rev >= 2 && phy->connected) - bcm43xx_calc_loopback_gain(bcm); - if (radio->revision != 8) { - if (radio->initval == 0xFFFF) - radio->initval = bcm43xx_radio_init2050(bcm); - else - bcm43xx_radio_write16(bcm, 0x0078, radio->initval); - } - if (radio->txctl2 == 0xFFFF) { - bcm43xx_phy_lo_g_measure(bcm); - } else { - if (radio->version == 0x2050 && radio->revision == 8) { - bcm43xx_radio_write16(bcm, 0x0052, - (radio->txctl1 << 4) | radio->txctl2); - } else { - bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) - & 0xFFF0) | radio->txctl1); - } - if (phy->rev >= 6) { - bcm43xx_phy_write(bcm, 0x0036, - (bcm43xx_phy_read(bcm, 0x0036) - & 0x0FFF) | (radio->txctl2 << 12)); - } - if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) - bcm43xx_phy_write(bcm, 0x002E, 0x8075); - else - bcm43xx_phy_write(bcm, 0x002E, 0x807F); - if (phy->rev < 2) - bcm43xx_phy_write(bcm, 0x002F, 0x0101); - else - bcm43xx_phy_write(bcm, 0x002F, 0x0202); - } - if (phy->connected || phy->rev >= 2) { - bcm43xx_phy_lo_adjust(bcm, 0); - bcm43xx_phy_write(bcm, 0x080F, 0x8078); - } - - if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { - /* The specs state to update the NRSSI LT with - * the value 0x7FFFFFFF here. I think that is some weird - * compiler optimization in the original driver. - * Essentially, what we do here is resetting all NRSSI LT - * entries to -32 (see the limit_value() in nrssi_hw_update()) - */ - bcm43xx_nrssi_hw_update(bcm, 0xFFFF); - bcm43xx_calc_nrssi_threshold(bcm); - } else if (phy->connected || phy->rev >= 2) { - if (radio->nrssi[0] == -1000) { - assert(radio->nrssi[1] == -1000); - bcm43xx_calc_nrssi_slope(bcm); - } else { - assert(radio->nrssi[1] != -1000); - bcm43xx_calc_nrssi_threshold(bcm); - } - } - if (radio->revision == 8) - bcm43xx_phy_write(bcm, 0x0805, 0x3230); - bcm43xx_phy_init_pctl(bcm); - if (bcm->chip_id == 0x4306 && bcm->chip_package == 2) { - bcm43xx_phy_write(bcm, 0x0429, - bcm43xx_phy_read(bcm, 0x0429) & 0xBFFF); - bcm43xx_phy_write(bcm, 0x04C3, - bcm43xx_phy_read(bcm, 0x04C3) & 0x7FFF); - } -} - -static u16 bcm43xx_phy_lo_b_r15_loop(struct bcm43xx_private *bcm) -{ - int i; - u16 ret = 0; - unsigned long flags; - - local_irq_save(flags); - for (i = 0; i < 10; i++){ - bcm43xx_phy_write(bcm, 0x0015, 0xAFA0); - udelay(1); - bcm43xx_phy_write(bcm, 0x0015, 0xEFA0); - udelay(10); - bcm43xx_phy_write(bcm, 0x0015, 0xFFA0); - udelay(40); - ret += bcm43xx_phy_read(bcm, 0x002C); - } - local_irq_restore(flags); - bcm43xx_voluntary_preempt(); - - return ret; -} - -void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 regstack[12] = { 0 }; - u16 mls; - u16 fval; - int i, j; - - regstack[0] = bcm43xx_phy_read(bcm, 0x0015); - regstack[1] = bcm43xx_radio_read16(bcm, 0x0052) & 0xFFF0; - - if (radio->version == 0x2053) { - regstack[2] = bcm43xx_phy_read(bcm, 0x000A); - regstack[3] = bcm43xx_phy_read(bcm, 0x002A); - regstack[4] = bcm43xx_phy_read(bcm, 0x0035); - regstack[5] = bcm43xx_phy_read(bcm, 0x0003); - regstack[6] = bcm43xx_phy_read(bcm, 0x0001); - regstack[7] = bcm43xx_phy_read(bcm, 0x0030); - - regstack[8] = bcm43xx_radio_read16(bcm, 0x0043); - regstack[9] = bcm43xx_radio_read16(bcm, 0x007A); - regstack[10] = bcm43xx_read16(bcm, 0x03EC); - regstack[11] = bcm43xx_radio_read16(bcm, 0x0052) & 0x00F0; - - bcm43xx_phy_write(bcm, 0x0030, 0x00FF); - bcm43xx_write16(bcm, 0x03EC, 0x3F3F); - bcm43xx_phy_write(bcm, 0x0035, regstack[4] & 0xFF7F); - bcm43xx_radio_write16(bcm, 0x007A, regstack[9] & 0xFFF0); - } - bcm43xx_phy_write(bcm, 0x0015, 0xB000); - bcm43xx_phy_write(bcm, 0x002B, 0x0004); - - if (radio->version == 0x2053) { - bcm43xx_phy_write(bcm, 0x002B, 0x0203); - bcm43xx_phy_write(bcm, 0x002A, 0x08A3); - } - - phy->minlowsig[0] = 0xFFFF; - - for (i = 0; i < 4; i++) { - bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i); - bcm43xx_phy_lo_b_r15_loop(bcm); - } - for (i = 0; i < 10; i++) { - bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | i); - mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10; - if (mls < phy->minlowsig[0]) { - phy->minlowsig[0] = mls; - phy->minlowsigpos[0] = i; - } - } - bcm43xx_radio_write16(bcm, 0x0052, regstack[1] | phy->minlowsigpos[0]); - - phy->minlowsig[1] = 0xFFFF; - - for (i = -4; i < 5; i += 2) { - for (j = -4; j < 5; j += 2) { - if (j < 0) - fval = (0x0100 * i) + j + 0x0100; - else - fval = (0x0100 * i) + j; - bcm43xx_phy_write(bcm, 0x002F, fval); - mls = bcm43xx_phy_lo_b_r15_loop(bcm) / 10; - if (mls < phy->minlowsig[1]) { - phy->minlowsig[1] = mls; - phy->minlowsigpos[1] = fval; - } - } - } - phy->minlowsigpos[1] += 0x0101; - - bcm43xx_phy_write(bcm, 0x002F, phy->minlowsigpos[1]); - if (radio->version == 0x2053) { - bcm43xx_phy_write(bcm, 0x000A, regstack[2]); - bcm43xx_phy_write(bcm, 0x002A, regstack[3]); - bcm43xx_phy_write(bcm, 0x0035, regstack[4]); - bcm43xx_phy_write(bcm, 0x0003, regstack[5]); - bcm43xx_phy_write(bcm, 0x0001, regstack[6]); - bcm43xx_phy_write(bcm, 0x0030, regstack[7]); - - bcm43xx_radio_write16(bcm, 0x0043, regstack[8]); - bcm43xx_radio_write16(bcm, 0x007A, regstack[9]); - - bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) & 0x000F) - | regstack[11]); - - bcm43xx_write16(bcm, 0x03EC, regstack[10]); - } - bcm43xx_phy_write(bcm, 0x0015, regstack[0]); -} - -static inline -u16 bcm43xx_phy_lo_g_deviation_subval(struct bcm43xx_private *bcm, u16 control) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 ret; - unsigned long flags; - - local_irq_save(flags); - if (phy->connected) { - bcm43xx_phy_write(bcm, 0x15, 0xE300); - control <<= 8; - bcm43xx_phy_write(bcm, 0x0812, control | 0x00B0); - udelay(5); - bcm43xx_phy_write(bcm, 0x0812, control | 0x00B2); - udelay(2); - bcm43xx_phy_write(bcm, 0x0812, control | 0x00B3); - udelay(4); - bcm43xx_phy_write(bcm, 0x0015, 0xF300); - udelay(8); - } else { - bcm43xx_phy_write(bcm, 0x0015, control | 0xEFA0); - udelay(2); - bcm43xx_phy_write(bcm, 0x0015, control | 0xEFE0); - udelay(4); - bcm43xx_phy_write(bcm, 0x0015, control | 0xFFE0); - udelay(8); - } - ret = bcm43xx_phy_read(bcm, 0x002D); - local_irq_restore(flags); - bcm43xx_voluntary_preempt(); - - return ret; -} - -static u32 bcm43xx_phy_lo_g_singledeviation(struct bcm43xx_private *bcm, u16 control) -{ - int i; - u32 ret = 0; - - for (i = 0; i < 8; i++) - ret += bcm43xx_phy_lo_g_deviation_subval(bcm, control); - - return ret; -} - -/* Write the LocalOscillator CONTROL */ -static inline -void bcm43xx_lo_write(struct bcm43xx_private *bcm, - struct bcm43xx_lopair *pair) -{ - u16 value; - - value = (u8)(pair->low); - value |= ((u8)(pair->high)) << 8; - -#ifdef CONFIG_BCM43XX_DEBUG - /* Sanity check. */ - if (pair->low < -8 || pair->low > 8 || - pair->high < -8 || pair->high > 8) { - printk(KERN_WARNING PFX - "WARNING: Writing invalid LOpair " - "(low: %d, high: %d, index: %lu)\n", - pair->low, pair->high, - (unsigned long)(pair - bcm43xx_current_phy(bcm)->_lo_pairs)); - dump_stack(); - } -#endif - - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, value); -} - -static inline -struct bcm43xx_lopair * bcm43xx_find_lopair(struct bcm43xx_private *bcm, - u16 baseband_attenuation, - u16 radio_attenuation, - u16 tx) -{ - static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (baseband_attenuation > 6) - baseband_attenuation = 6; - assert(radio_attenuation < 10); - - if (tx == 3) { - return bcm43xx_get_lopair(phy, - radio_attenuation, - baseband_attenuation); - } - return bcm43xx_get_lopair(phy, dict[radio_attenuation], baseband_attenuation); -} - -static inline -struct bcm43xx_lopair * bcm43xx_current_lopair(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - return bcm43xx_find_lopair(bcm, - radio->baseband_atten, - radio->radio_atten, - radio->txctl1); -} - -/* Adjust B/G LO */ -void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed) -{ - struct bcm43xx_lopair *pair; - - if (fixed) { - /* Use fixed values. Only for initialization. */ - pair = bcm43xx_find_lopair(bcm, 2, 3, 0); - } else - pair = bcm43xx_current_lopair(bcm); - bcm43xx_lo_write(bcm, pair); -} - -static void bcm43xx_phy_lo_g_measure_txctl2(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 txctl2 = 0, i; - u32 smallest, tmp; - - bcm43xx_radio_write16(bcm, 0x0052, 0x0000); - udelay(10); - smallest = bcm43xx_phy_lo_g_singledeviation(bcm, 0); - for (i = 0; i < 16; i++) { - bcm43xx_radio_write16(bcm, 0x0052, i); - udelay(10); - tmp = bcm43xx_phy_lo_g_singledeviation(bcm, 0); - if (tmp < smallest) { - smallest = tmp; - txctl2 = i; - } - } - radio->txctl2 = txctl2; -} - -static -void bcm43xx_phy_lo_g_state(struct bcm43xx_private *bcm, - const struct bcm43xx_lopair *in_pair, - struct bcm43xx_lopair *out_pair, - u16 r27) -{ - static const struct bcm43xx_lopair transitions[8] = { - { .high = 1, .low = 1, }, - { .high = 1, .low = 0, }, - { .high = 1, .low = -1, }, - { .high = 0, .low = -1, }, - { .high = -1, .low = -1, }, - { .high = -1, .low = 0, }, - { .high = -1, .low = 1, }, - { .high = 0, .low = 1, }, - }; - struct bcm43xx_lopair lowest_transition = { - .high = in_pair->high, - .low = in_pair->low, - }; - struct bcm43xx_lopair tmp_pair; - struct bcm43xx_lopair transition; - int i = 12; - int state = 0; - int found_lower; - int j, begin, end; - u32 lowest_deviation; - u32 tmp; - - /* Note that in_pair and out_pair can point to the same pair. Be careful. */ - - bcm43xx_lo_write(bcm, &lowest_transition); - lowest_deviation = bcm43xx_phy_lo_g_singledeviation(bcm, r27); - do { - found_lower = 0; - assert(state >= 0 && state <= 8); - if (state == 0) { - begin = 1; - end = 8; - } else if (state % 2 == 0) { - begin = state - 1; - end = state + 1; - } else { - begin = state - 2; - end = state + 2; - } - if (begin < 1) - begin += 8; - if (end > 8) - end -= 8; - - j = begin; - tmp_pair.high = lowest_transition.high; - tmp_pair.low = lowest_transition.low; - while (1) { - assert(j >= 1 && j <= 8); - transition.high = tmp_pair.high + transitions[j - 1].high; - transition.low = tmp_pair.low + transitions[j - 1].low; - if ((abs(transition.low) < 9) && (abs(transition.high) < 9)) { - bcm43xx_lo_write(bcm, &transition); - tmp = bcm43xx_phy_lo_g_singledeviation(bcm, r27); - if (tmp < lowest_deviation) { - lowest_deviation = tmp; - state = j; - found_lower = 1; - - lowest_transition.high = transition.high; - lowest_transition.low = transition.low; - } - } - if (j == end) - break; - if (j == 8) - j = 1; - else - j++; - } - } while (i-- && found_lower); - - out_pair->high = lowest_transition.high; - out_pair->low = lowest_transition.low; -} - -/* Set the baseband attenuation value on chip. */ -void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, - u16 baseband_attenuation) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 value; - - if (phy->analog == 0) { - value = (bcm43xx_read16(bcm, 0x03E6) & 0xFFF0); - value |= (baseband_attenuation & 0x000F); - bcm43xx_write16(bcm, 0x03E6, value); - return; - } - - if (phy->analog > 1) { - value = bcm43xx_phy_read(bcm, 0x0060) & ~0x003C; - value |= (baseband_attenuation << 2) & 0x003C; - } else { - value = bcm43xx_phy_read(bcm, 0x0060) & ~0x0078; - value |= (baseband_attenuation << 3) & 0x0078; - } - bcm43xx_phy_write(bcm, 0x0060, value); -} - -/* http://bcm-specs.sipsolutions.net/LocalOscillator/Measure */ -void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm) -{ - static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; - const int is_initializing = (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZING); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 h, i, oldi = 0, j; - struct bcm43xx_lopair control; - struct bcm43xx_lopair *tmp_control; - u16 tmp; - u16 regstack[16] = { 0 }; - u8 oldchannel; - - //XXX: What are these? - u8 r27 = 0, r31; - - oldchannel = radio->channel; - /* Setup */ - if (phy->connected) { - regstack[0] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); - regstack[1] = bcm43xx_phy_read(bcm, 0x0802); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF); - bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC); - } - regstack[3] = bcm43xx_read16(bcm, 0x03E2); - bcm43xx_write16(bcm, 0x03E2, regstack[3] | 0x8000); - regstack[4] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); - regstack[5] = bcm43xx_phy_read(bcm, 0x15); - regstack[6] = bcm43xx_phy_read(bcm, 0x2A); - regstack[7] = bcm43xx_phy_read(bcm, 0x35); - regstack[8] = bcm43xx_phy_read(bcm, 0x60); - regstack[9] = bcm43xx_radio_read16(bcm, 0x43); - regstack[10] = bcm43xx_radio_read16(bcm, 0x7A); - regstack[11] = bcm43xx_radio_read16(bcm, 0x52); - if (phy->connected) { - regstack[12] = bcm43xx_phy_read(bcm, 0x0811); - regstack[13] = bcm43xx_phy_read(bcm, 0x0812); - regstack[14] = bcm43xx_phy_read(bcm, 0x0814); - regstack[15] = bcm43xx_phy_read(bcm, 0x0815); - } - bcm43xx_radio_selectchannel(bcm, 6, 0); - if (phy->connected) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0] & 0x7FFF); - bcm43xx_phy_write(bcm, 0x0802, regstack[1] & 0xFFFC); - bcm43xx_dummy_transmission(bcm); - } - bcm43xx_radio_write16(bcm, 0x0043, 0x0006); - - bcm43xx_phy_set_baseband_attenuation(bcm, 2); - - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, 0x0000); - bcm43xx_phy_write(bcm, 0x002E, 0x007F); - bcm43xx_phy_write(bcm, 0x080F, 0x0078); - bcm43xx_phy_write(bcm, 0x0035, regstack[7] & ~(1 << 7)); - bcm43xx_radio_write16(bcm, 0x007A, regstack[10] & 0xFFF0); - bcm43xx_phy_write(bcm, 0x002B, 0x0203); - bcm43xx_phy_write(bcm, 0x002A, 0x08A3); - if (phy->connected) { - bcm43xx_phy_write(bcm, 0x0814, regstack[14] | 0x0003); - bcm43xx_phy_write(bcm, 0x0815, regstack[15] & 0xFFFC); - bcm43xx_phy_write(bcm, 0x0811, 0x01B3); - bcm43xx_phy_write(bcm, 0x0812, 0x00B2); - } - if (is_initializing) - bcm43xx_phy_lo_g_measure_txctl2(bcm); - bcm43xx_phy_write(bcm, 0x080F, 0x8078); - - /* Measure */ - control.low = 0; - control.high = 0; - for (h = 0; h < 10; h++) { - /* Loop over each possible RadioAttenuation (0-9) */ - i = pairorder[h]; - if (is_initializing) { - if (i == 3) { - control.low = 0; - control.high = 0; - } else if (((i % 2 == 1) && (oldi % 2 == 1)) || - ((i % 2 == 0) && (oldi % 2 == 0))) { - tmp_control = bcm43xx_get_lopair(phy, oldi, 0); - memcpy(&control, tmp_control, sizeof(control)); - } else { - tmp_control = bcm43xx_get_lopair(phy, 3, 0); - memcpy(&control, tmp_control, sizeof(control)); - } - } - /* Loop over each possible BasebandAttenuation/2 */ - for (j = 0; j < 4; j++) { - if (is_initializing) { - tmp = i * 2 + j; - r27 = 0; - r31 = 0; - if (tmp > 14) { - r31 = 1; - if (tmp > 17) - r27 = 1; - if (tmp > 19) - r27 = 2; - } - } else { - tmp_control = bcm43xx_get_lopair(phy, i, j * 2); - if (!tmp_control->used) - continue; - memcpy(&control, tmp_control, sizeof(control)); - r27 = 3; - r31 = 0; - } - bcm43xx_radio_write16(bcm, 0x43, i); - bcm43xx_radio_write16(bcm, 0x52, radio->txctl2); - udelay(10); - bcm43xx_voluntary_preempt(); - - bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); - - tmp = (regstack[10] & 0xFFF0); - if (r31) - tmp |= 0x0008; - bcm43xx_radio_write16(bcm, 0x007A, tmp); - - tmp_control = bcm43xx_get_lopair(phy, i, j * 2); - bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27); - } - oldi = i; - } - /* Loop over each possible RadioAttenuation (10-13) */ - for (i = 10; i < 14; i++) { - /* Loop over each possible BasebandAttenuation/2 */ - for (j = 0; j < 4; j++) { - if (is_initializing) { - tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2); - memcpy(&control, tmp_control, sizeof(control)); - tmp = (i - 9) * 2 + j - 5;//FIXME: This is wrong, as the following if statement can never trigger. - r27 = 0; - r31 = 0; - if (tmp > 14) { - r31 = 1; - if (tmp > 17) - r27 = 1; - if (tmp > 19) - r27 = 2; - } - } else { - tmp_control = bcm43xx_get_lopair(phy, i - 9, j * 2); - if (!tmp_control->used) - continue; - memcpy(&control, tmp_control, sizeof(control)); - r27 = 3; - r31 = 0; - } - bcm43xx_radio_write16(bcm, 0x43, i - 9); - bcm43xx_radio_write16(bcm, 0x52, - radio->txctl2 - | (3/*txctl1*/ << 4));//FIXME: shouldn't txctl1 be zero here and 3 in the loop above? - udelay(10); - bcm43xx_voluntary_preempt(); - - bcm43xx_phy_set_baseband_attenuation(bcm, j * 2); - - tmp = (regstack[10] & 0xFFF0); - if (r31) - tmp |= 0x0008; - bcm43xx_radio_write16(bcm, 0x7A, tmp); - - tmp_control = bcm43xx_get_lopair(phy, i, j * 2); - bcm43xx_phy_lo_g_state(bcm, &control, tmp_control, r27); - } - } - - /* Restoration */ - if (phy->connected) { - bcm43xx_phy_write(bcm, 0x0015, 0xE300); - bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA0); - udelay(5); - bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA2); - udelay(2); - bcm43xx_phy_write(bcm, 0x0812, (r27 << 8) | 0xA3); - bcm43xx_voluntary_preempt(); - } else - bcm43xx_phy_write(bcm, 0x0015, r27 | 0xEFA0); - bcm43xx_phy_lo_adjust(bcm, is_initializing); - bcm43xx_phy_write(bcm, 0x002E, 0x807F); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x002F, 0x0202); - else - bcm43xx_phy_write(bcm, 0x002F, 0x0101); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, regstack[4]); - bcm43xx_phy_write(bcm, 0x0015, regstack[5]); - bcm43xx_phy_write(bcm, 0x002A, regstack[6]); - bcm43xx_phy_write(bcm, 0x0035, regstack[7]); - bcm43xx_phy_write(bcm, 0x0060, regstack[8]); - bcm43xx_radio_write16(bcm, 0x0043, regstack[9]); - bcm43xx_radio_write16(bcm, 0x007A, regstack[10]); - regstack[11] &= 0x00F0; - regstack[11] |= (bcm43xx_radio_read16(bcm, 0x52) & 0x000F); - bcm43xx_radio_write16(bcm, 0x52, regstack[11]); - bcm43xx_write16(bcm, 0x03E2, regstack[3]); - if (phy->connected) { - bcm43xx_phy_write(bcm, 0x0811, regstack[12]); - bcm43xx_phy_write(bcm, 0x0812, regstack[13]); - bcm43xx_phy_write(bcm, 0x0814, regstack[14]); - bcm43xx_phy_write(bcm, 0x0815, regstack[15]); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, regstack[0]); - bcm43xx_phy_write(bcm, 0x0802, regstack[1]); - } - bcm43xx_radio_selectchannel(bcm, oldchannel, 1); - -#ifdef CONFIG_BCM43XX_DEBUG - { - /* Sanity check for all lopairs. */ - for (i = 0; i < BCM43xx_LO_COUNT; i++) { - tmp_control = phy->_lo_pairs + i; - if (tmp_control->low < -8 || tmp_control->low > 8 || - tmp_control->high < -8 || tmp_control->high > 8) { - printk(KERN_WARNING PFX - "WARNING: Invalid LOpair (low: %d, high: %d, index: %d)\n", - tmp_control->low, tmp_control->high, i); - } - } - } -#endif /* CONFIG_BCM43XX_DEBUG */ -} - -static -void bcm43xx_phy_lo_mark_current_used(struct bcm43xx_private *bcm) -{ - struct bcm43xx_lopair *pair; - - pair = bcm43xx_current_lopair(bcm); - pair->used = 1; -} - -void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_lopair *pair; - int i; - - for (i = 0; i < BCM43xx_LO_COUNT; i++) { - pair = phy->_lo_pairs + i; - pair->used = 0; - } -} - -/* http://bcm-specs.sipsolutions.net/EstimatePowerOut - * This function converts a TSSI value to dBm in Q5.2 - */ -static s8 bcm43xx_phy_estimate_power_out(struct bcm43xx_private *bcm, s8 tssi) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - s8 dbm = 0; - s32 tmp; - - tmp = phy->idle_tssi; - tmp += tssi; - tmp -= phy->savedpctlreg; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - tmp += 0x80; - tmp = limit_value(tmp, 0x00, 0xFF); - dbm = phy->tssi2dbm[tmp]; - TODO(); //TODO: There's a FIXME on the specs - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - tmp = limit_value(tmp, 0x00, 0x3F); - dbm = phy->tssi2dbm[tmp]; - break; - default: - assert(0); - } - - return dbm; -} - -/* http://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ -void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (phy->savedpctlreg == 0xFFFF) - return; - if ((bcm->board_type == 0x0416) && - (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM)) - return; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: { - - TODO(); //TODO: Nothing for A PHYs yet :-/ - - break; - } - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: { - u16 tmp; - u16 txpower; - s8 v0, v1, v2, v3; - s8 average; - u8 max_pwr; - s16 desired_pwr, estimated_pwr, pwr_adjust; - s16 radio_att_delta, baseband_att_delta; - s16 radio_attenuation, baseband_attenuation; - unsigned long phylock_flags; - - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0058); - v0 = (s8)(tmp & 0x00FF); - v1 = (s8)((tmp & 0xFF00) >> 8); - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005A); - v2 = (s8)(tmp & 0x00FF); - v3 = (s8)((tmp & 0xFF00) >> 8); - tmp = 0; - - if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) { - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0070); - v0 = (s8)(tmp & 0x00FF); - v1 = (s8)((tmp & 0xFF00) >> 8); - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0072); - v2 = (s8)(tmp & 0x00FF); - v3 = (s8)((tmp & 0xFF00) >> 8); - if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) - return; - v0 = (v0 + 0x20) & 0x3F; - v1 = (v1 + 0x20) & 0x3F; - v2 = (v2 + 0x20) & 0x3F; - v3 = (v3 + 0x20) & 0x3F; - tmp = 1; - } - bcm43xx_radio_clear_tssi(bcm); - - average = (v0 + v1 + v2 + v3 + 2) / 4; - - if (tmp && (bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x005E) & 0x8)) - average -= 13; - - estimated_pwr = bcm43xx_phy_estimate_power_out(bcm, average); - - max_pwr = bcm->sprom.maxpower_bgphy; - - if ((bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) && - (phy->type == BCM43xx_PHYTYPE_G)) - max_pwr -= 0x3; - - /*TODO: - max_pwr = min(REG - bcm->sprom.antennagain_bgphy - 0x6, max_pwr) - where REG is the max power as per the regulatory domain - */ - - desired_pwr = limit_value(radio->txpower_desired, 0, max_pwr); - /* Check if we need to adjust the current power. */ - pwr_adjust = desired_pwr - estimated_pwr; - radio_att_delta = -(pwr_adjust + 7) >> 3; - baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); - if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { - bcm43xx_phy_lo_mark_current_used(bcm); - return; - } - - /* Calculate the new attenuation values. */ - baseband_attenuation = radio->baseband_atten; - baseband_attenuation += baseband_att_delta; - radio_attenuation = radio->radio_atten; - radio_attenuation += radio_att_delta; - - /* Get baseband and radio attenuation values into their permitted ranges. - * baseband 0-11, radio 0-9. - * Radio attenuation affects power level 4 times as much as baseband. - */ - if (radio_attenuation < 0) { - baseband_attenuation -= (4 * -radio_attenuation); - radio_attenuation = 0; - } else if (radio_attenuation > 9) { - baseband_attenuation += (4 * (radio_attenuation - 9)); - radio_attenuation = 9; - } else { - while (baseband_attenuation < 0 && radio_attenuation > 0) { - baseband_attenuation += 4; - radio_attenuation--; - } - while (baseband_attenuation > 11 && radio_attenuation < 9) { - baseband_attenuation -= 4; - radio_attenuation++; - } - } - baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - - txpower = radio->txctl1; - if ((radio->version == 0x2050) && (radio->revision == 2)) { - if (radio_attenuation <= 1) { - if (txpower == 0) { - txpower = 3; - radio_attenuation += 2; - baseband_attenuation += 2; - } else if (bcm->sprom.boardflags & BCM43xx_BFL_PACTRL) { - baseband_attenuation += 4 * (radio_attenuation - 2); - radio_attenuation = 2; - } - } else if (radio_attenuation > 4 && txpower != 0) { - txpower = 0; - if (baseband_attenuation < 3) { - radio_attenuation -= 3; - baseband_attenuation += 2; - } else { - radio_attenuation -= 2; - baseband_attenuation -= 2; - } - } - } - radio->txctl1 = txpower; - baseband_attenuation = limit_value(baseband_attenuation, 0, 11); - radio_attenuation = limit_value(radio_attenuation, 0, 9); - - bcm43xx_phy_lock(bcm, phylock_flags); - bcm43xx_radio_lock(bcm); - bcm43xx_radio_set_txpower_bg(bcm, baseband_attenuation, - radio_attenuation, txpower); - bcm43xx_phy_lo_mark_current_used(bcm); - bcm43xx_radio_unlock(bcm); - bcm43xx_phy_unlock(bcm, phylock_flags); - break; - } - default: - assert(0); - } -} - -static inline -s32 bcm43xx_tssi2dbm_ad(s32 num, s32 den) -{ - if (num < 0) - return num/den; - else - return (num+den/2)/den; -} - -static inline -s8 bcm43xx_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2) -{ - s32 m1, m2, f = 256, q, delta; - s8 i = 0; - - m1 = bcm43xx_tssi2dbm_ad(16 * pab0 + index * pab1, 32); - m2 = max(bcm43xx_tssi2dbm_ad(32768 + index * pab2, 256), 1); - do { - if (i > 15) - return -EINVAL; - q = bcm43xx_tssi2dbm_ad(f * 4096 - - bcm43xx_tssi2dbm_ad(m2 * f, 16) * f, 2048); - delta = abs(q - f); - f = q; - i++; - } while (delta >= 2); - entry[index] = limit_value(bcm43xx_tssi2dbm_ad(m1 * f, 8192), -127, 128); - return 0; -} - -/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */ -int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - s16 pab0, pab1, pab2; - u8 idx; - s8 *dyn_tssi2dbm; - - if (phy->type == BCM43xx_PHYTYPE_A) { - pab0 = (s16)(bcm->sprom.pa1b0); - pab1 = (s16)(bcm->sprom.pa1b1); - pab2 = (s16)(bcm->sprom.pa1b2); - } else { - pab0 = (s16)(bcm->sprom.pa0b0); - pab1 = (s16)(bcm->sprom.pa0b1); - pab2 = (s16)(bcm->sprom.pa0b2); - } - - if ((bcm->chip_id == 0x4301) && (radio->version != 0x2050)) { - phy->idle_tssi = 0x34; - phy->tssi2dbm = bcm43xx_tssi2dbm_b_table; - return 0; - } - - if (pab0 != 0 && pab1 != 0 && pab2 != 0 && - pab0 != -1 && pab1 != -1 && pab2 != -1) { - /* The pabX values are set in SPROM. Use them. */ - if (phy->type == BCM43xx_PHYTYPE_A) { - if ((s8)bcm->sprom.idle_tssi_tgt_aphy != 0 && - (s8)bcm->sprom.idle_tssi_tgt_aphy != -1) - phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_aphy); - else - phy->idle_tssi = 62; - } else { - if ((s8)bcm->sprom.idle_tssi_tgt_bgphy != 0 && - (s8)bcm->sprom.idle_tssi_tgt_bgphy != -1) - phy->idle_tssi = (s8)(bcm->sprom.idle_tssi_tgt_bgphy); - else - phy->idle_tssi = 62; - } - dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); - if (dyn_tssi2dbm == NULL) { - printk(KERN_ERR PFX "Could not allocate memory " - "for tssi2dbm table\n"); - return -ENOMEM; - } - for (idx = 0; idx < 64; idx++) - if (bcm43xx_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, pab1, pab2)) { - phy->tssi2dbm = NULL; - printk(KERN_ERR PFX "Could not generate " - "tssi2dBm table\n"); - kfree(dyn_tssi2dbm); - return -ENODEV; - } - phy->tssi2dbm = dyn_tssi2dbm; - phy->dyn_tssi_tbl = 1; - } else { - /* pabX values not set in SPROM. */ - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - /* APHY needs a generated table. */ - phy->tssi2dbm = NULL; - printk(KERN_ERR PFX "Could not generate tssi2dBm " - "table (wrong SPROM info)!\n"); - return -ENODEV; - case BCM43xx_PHYTYPE_B: - phy->idle_tssi = 0x34; - phy->tssi2dbm = bcm43xx_tssi2dbm_b_table; - break; - case BCM43xx_PHYTYPE_G: - phy->idle_tssi = 0x34; - phy->tssi2dbm = bcm43xx_tssi2dbm_g_table; - break; - } - } - - return 0; -} - -int bcm43xx_phy_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - int err = -ENODEV; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - if (phy->rev == 2 || phy->rev == 3) { - bcm43xx_phy_inita(bcm); - err = 0; - } - break; - case BCM43xx_PHYTYPE_B: - switch (phy->rev) { - case 2: - bcm43xx_phy_initb2(bcm); - err = 0; - break; - case 4: - bcm43xx_phy_initb4(bcm); - err = 0; - break; - case 5: - bcm43xx_phy_initb5(bcm); - err = 0; - break; - case 6: - bcm43xx_phy_initb6(bcm); - err = 0; - break; - } - break; - case BCM43xx_PHYTYPE_G: - bcm43xx_phy_initg(bcm); - err = 0; - break; - } - if (err) - printk(KERN_WARNING PFX "Unknown PHYTYPE found!\n"); - - return err; -} - -void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 antennadiv; - u16 offset; - u16 value; - u32 ucodeflags; - - antennadiv = phy->antenna_diversity; - - if (antennadiv == 0xFFFF) - antennadiv = 3; - assert(antennadiv <= 3); - - ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - ucodeflags & ~BCM43xx_UCODEFLAG_AUTODIV); - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - case BCM43xx_PHYTYPE_G: - if (phy->type == BCM43xx_PHYTYPE_A) - offset = 0x0000; - else - offset = 0x0400; - - if (antennadiv == 2) - value = (3/*automatic*/ << 7); - else - value = (antennadiv << 7); - bcm43xx_phy_write(bcm, offset + 1, - (bcm43xx_phy_read(bcm, offset + 1) - & 0x7E7F) | value); - - if (antennadiv >= 2) { - if (antennadiv == 2) - value = (antennadiv << 7); - else - value = (0/*force0*/ << 7); - bcm43xx_phy_write(bcm, offset + 0x2B, - (bcm43xx_phy_read(bcm, offset + 0x2B) - & 0xFEFF) | value); - } - - if (phy->type == BCM43xx_PHYTYPE_G) { - if (antennadiv >= 2) - bcm43xx_phy_write(bcm, 0x048C, - bcm43xx_phy_read(bcm, 0x048C) - | 0x2000); - else - bcm43xx_phy_write(bcm, 0x048C, - bcm43xx_phy_read(bcm, 0x048C) - & ~0x2000); - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0461, - bcm43xx_phy_read(bcm, 0x0461) - | 0x0010); - bcm43xx_phy_write(bcm, 0x04AD, - (bcm43xx_phy_read(bcm, 0x04AD) - & 0x00FF) | 0x0015); - if (phy->rev == 2) - bcm43xx_phy_write(bcm, 0x0427, 0x0008); - else - bcm43xx_phy_write(bcm, 0x0427, - (bcm43xx_phy_read(bcm, 0x0427) - & 0x00FF) | 0x0008); - } - else if (phy->rev >= 6) - bcm43xx_phy_write(bcm, 0x049B, 0x00DC); - } else { - if (phy->rev < 3) - bcm43xx_phy_write(bcm, 0x002B, - (bcm43xx_phy_read(bcm, 0x002B) - & 0x00FF) | 0x0024); - else { - bcm43xx_phy_write(bcm, 0x0061, - bcm43xx_phy_read(bcm, 0x0061) - | 0x0010); - if (phy->rev == 3) { - bcm43xx_phy_write(bcm, 0x0093, 0x001D); - bcm43xx_phy_write(bcm, 0x0027, 0x0008); - } else { - bcm43xx_phy_write(bcm, 0x0093, 0x003A); - bcm43xx_phy_write(bcm, 0x0027, - (bcm43xx_phy_read(bcm, 0x0027) - & 0x00FF) | 0x0008); - } - } - } - break; - case BCM43xx_PHYTYPE_B: - if (bcm->current_core->rev == 2) - value = (3/*automatic*/ << 7); - else - value = (antennadiv << 7); - bcm43xx_phy_write(bcm, 0x03E2, - (bcm43xx_phy_read(bcm, 0x03E2) - & 0xFE7F) | value); - break; - default: - assert(0); - } - - if (antennadiv >= 2) { - ucodeflags = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET); - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - ucodeflags | BCM43xx_UCODEFLAG_AUTODIV); - } - - phy->antenna_diversity = antennadiv; -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h b/drivers/net/wireless/bcm43xx/bcm43xx_phy.h deleted file mode 100644 index 73118364b552..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_phy.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_PHY_H_ -#define BCM43xx_PHY_H_ - -#include - -struct bcm43xx_private; - -void bcm43xx_raw_phy_lock(struct bcm43xx_private *bcm); -#define bcm43xx_phy_lock(bcm, flags) \ - do { \ - local_irq_save(flags); \ - bcm43xx_raw_phy_lock(bcm); \ - } while (0) -void bcm43xx_raw_phy_unlock(struct bcm43xx_private *bcm); -#define bcm43xx_phy_unlock(bcm, flags) \ - do { \ - bcm43xx_raw_phy_unlock(bcm); \ - local_irq_restore(flags); \ - } while (0) - -/* Card uses the loopback gain stuff */ -#define has_loopback_gain(phy) \ - (((phy)->rev > 1) || ((phy)->connected)) - -u16 bcm43xx_phy_read(struct bcm43xx_private *bcm, u16 offset); -void bcm43xx_phy_write(struct bcm43xx_private *bcm, u16 offset, u16 val); - -int bcm43xx_phy_init_tssi2dbm_table(struct bcm43xx_private *bcm); -int bcm43xx_phy_init(struct bcm43xx_private *bcm); - -void bcm43xx_phy_set_antenna_diversity(struct bcm43xx_private *bcm); -void bcm43xx_phy_calibrate(struct bcm43xx_private *bcm); -int bcm43xx_phy_connect(struct bcm43xx_private *bcm, int connect); - -void bcm43xx_phy_lo_b_measure(struct bcm43xx_private *bcm); -void bcm43xx_phy_lo_g_measure(struct bcm43xx_private *bcm); -void bcm43xx_phy_xmitpower(struct bcm43xx_private *bcm); - -/* Adjust the LocalOscillator to the saved values. - * "fixed" is only set to 1 once in initialization. Set to 0 otherwise. - */ -void bcm43xx_phy_lo_adjust(struct bcm43xx_private *bcm, int fixed); -void bcm43xx_phy_lo_mark_all_unused(struct bcm43xx_private *bcm); - -void bcm43xx_phy_set_baseband_attenuation(struct bcm43xx_private *bcm, - u16 baseband_attenuation); - -#endif /* BCM43xx_PHY_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c b/drivers/net/wireless/bcm43xx/bcm43xx_pio.c deleted file mode 100644 index 76ab109cd2db..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - PIO Transmission - - Copyright (c) 2005 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx.h" -#include "bcm43xx_pio.h" -#include "bcm43xx_main.h" -#include "bcm43xx_xmit.h" -#include "bcm43xx_power.h" - -#include - - -static void tx_start(struct bcm43xx_pioqueue *queue) -{ - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_INIT); -} - -static void tx_octet(struct bcm43xx_pioqueue *queue, - u8 octet) -{ - if (queue->need_workarounds) { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, - octet); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO); - } else { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, - octet); - } -} - -static u16 tx_get_next_word(struct bcm43xx_txhdr *txhdr, - const u8 *packet, - unsigned int *pos) -{ - const u8 *source; - unsigned int i = *pos; - u16 ret; - - if (i < sizeof(*txhdr)) { - source = (const u8 *)txhdr; - } else { - source = packet; - i -= sizeof(*txhdr); - } - ret = le16_to_cpu( *((__le16 *)(source + i)) ); - *pos += 2; - - return ret; -} - -static void tx_data(struct bcm43xx_pioqueue *queue, - struct bcm43xx_txhdr *txhdr, - const u8 *packet, - unsigned int octets) -{ - u16 data; - unsigned int i = 0; - - if (queue->need_workarounds) { - data = tx_get_next_word(txhdr, packet, &i); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); - } - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO | - BCM43xx_PIO_TXCTL_WRITEHI); - while (i < octets - 1) { - data = tx_get_next_word(txhdr, packet, &i); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, data); - } - if (octets % 2) - tx_octet(queue, packet[octets - sizeof(*txhdr) - 1]); -} - -static void tx_complete(struct bcm43xx_pioqueue *queue, - struct sk_buff *skb) -{ - if (queue->need_workarounds) { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXDATA, - skb->data[skb->len - 1]); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_WRITELO | - BCM43xx_PIO_TXCTL_COMPLETE); - } else { - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - BCM43xx_PIO_TXCTL_COMPLETE); - } -} - -static u16 generate_cookie(struct bcm43xx_pioqueue *queue, - struct bcm43xx_pio_txpacket *packet) -{ - u16 cookie = 0x0000; - int packetindex; - - /* We use the upper 4 bits for the PIO - * controller ID and the lower 12 bits - * for the packet index (in the cache). - */ - switch (queue->mmio_base) { - case BCM43xx_MMIO_PIO1_BASE: - break; - case BCM43xx_MMIO_PIO2_BASE: - cookie = 0x1000; - break; - case BCM43xx_MMIO_PIO3_BASE: - cookie = 0x2000; - break; - case BCM43xx_MMIO_PIO4_BASE: - cookie = 0x3000; - break; - default: - assert(0); - } - packetindex = pio_txpacket_getindex(packet); - assert(((u16)packetindex & 0xF000) == 0x0000); - cookie |= (u16)packetindex; - - return cookie; -} - -static -struct bcm43xx_pioqueue * parse_cookie(struct bcm43xx_private *bcm, - u16 cookie, - struct bcm43xx_pio_txpacket **packet) -{ - struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); - struct bcm43xx_pioqueue *queue = NULL; - int packetindex; - - switch (cookie & 0xF000) { - case 0x0000: - queue = pio->queue0; - break; - case 0x1000: - queue = pio->queue1; - break; - case 0x2000: - queue = pio->queue2; - break; - case 0x3000: - queue = pio->queue3; - break; - default: - assert(0); - } - packetindex = (cookie & 0x0FFF); - assert(packetindex >= 0 && packetindex < BCM43xx_PIO_MAXTXPACKETS); - *packet = &(queue->tx_packets_cache[packetindex]); - - return queue; -} - -static void pio_tx_write_fragment(struct bcm43xx_pioqueue *queue, - struct sk_buff *skb, - struct bcm43xx_pio_txpacket *packet) -{ - struct bcm43xx_txhdr txhdr; - unsigned int octets; - - assert(skb_shinfo(skb)->nr_frags == 0); - bcm43xx_generate_txhdr(queue->bcm, - &txhdr, skb->data, skb->len, - (packet->xmitted_frags == 0), - generate_cookie(queue, packet)); - - tx_start(queue); - octets = skb->len + sizeof(txhdr); - if (queue->need_workarounds) - octets--; - tx_data(queue, &txhdr, (u8 *)skb->data, octets); - tx_complete(queue, skb); -} - -static void free_txpacket(struct bcm43xx_pio_txpacket *packet, - int irq_context) -{ - struct bcm43xx_pioqueue *queue = packet->queue; - - ieee80211_txb_free(packet->txb); - list_move(&packet->list, &queue->txfree); - queue->nr_txfree++; - - assert(queue->tx_devq_used >= packet->xmitted_octets); - assert(queue->tx_devq_packets >= packet->xmitted_frags); - queue->tx_devq_used -= packet->xmitted_octets; - queue->tx_devq_packets -= packet->xmitted_frags; -} - -static int pio_tx_packet(struct bcm43xx_pio_txpacket *packet) -{ - struct bcm43xx_pioqueue *queue = packet->queue; - struct ieee80211_txb *txb = packet->txb; - struct sk_buff *skb; - u16 octets; - int i; - - for (i = packet->xmitted_frags; i < txb->nr_frags; i++) { - skb = txb->fragments[i]; - - octets = (u16)skb->len + sizeof(struct bcm43xx_txhdr); - assert(queue->tx_devq_size >= octets); - assert(queue->tx_devq_packets <= BCM43xx_PIO_MAXTXDEVQPACKETS); - assert(queue->tx_devq_used <= queue->tx_devq_size); - /* Check if there is sufficient free space on the device - * TX queue. If not, return and let the TX tasklet - * retry later. - */ - if (queue->tx_devq_packets == BCM43xx_PIO_MAXTXDEVQPACKETS) - return -EBUSY; - if (queue->tx_devq_used + octets > queue->tx_devq_size) - return -EBUSY; - /* Now poke the device. */ - pio_tx_write_fragment(queue, skb, packet); - - /* Account for the packet size. - * (We must not overflow the device TX queue) - */ - queue->tx_devq_packets++; - queue->tx_devq_used += octets; - - assert(packet->xmitted_frags < packet->txb->nr_frags); - packet->xmitted_frags++; - packet->xmitted_octets += octets; - } - list_move_tail(&packet->list, &queue->txrunning); - - return 0; -} - -static void tx_tasklet(unsigned long d) -{ - struct bcm43xx_pioqueue *queue = (struct bcm43xx_pioqueue *)d; - struct bcm43xx_private *bcm = queue->bcm; - unsigned long flags; - struct bcm43xx_pio_txpacket *packet, *tmp_packet; - int err; - u16 txctl; - - spin_lock_irqsave(&bcm->irq_lock, flags); - - if (queue->tx_frozen) - goto out_unlock; - txctl = bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL); - if (txctl & BCM43xx_PIO_TXCTL_SUSPEND) - goto out_unlock; - - list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) { - assert(packet->xmitted_frags < packet->txb->nr_frags); - if (packet->xmitted_frags == 0) { - int i; - struct sk_buff *skb; - - /* Check if the device queue is big - * enough for every fragment. If not, drop the - * whole packet. - */ - for (i = 0; i < packet->txb->nr_frags; i++) { - skb = packet->txb->fragments[i]; - if (unlikely(skb->len > queue->tx_devq_size)) { - dprintkl(KERN_ERR PFX "PIO TX device queue too small. " - "Dropping packet.\n"); - free_txpacket(packet, 1); - goto next_packet; - } - } - } - /* Try to transmit the packet. - * This may not completely succeed. - */ - err = pio_tx_packet(packet); - if (err) - break; - next_packet: - continue; - } -out_unlock: - spin_unlock_irqrestore(&bcm->irq_lock, flags); -} - -static void setup_txqueues(struct bcm43xx_pioqueue *queue) -{ - struct bcm43xx_pio_txpacket *packet; - int i; - - queue->nr_txfree = BCM43xx_PIO_MAXTXPACKETS; - for (i = 0; i < BCM43xx_PIO_MAXTXPACKETS; i++) { - packet = &(queue->tx_packets_cache[i]); - - packet->queue = queue; - INIT_LIST_HEAD(&packet->list); - - list_add(&packet->list, &queue->txfree); - } -} - -static -struct bcm43xx_pioqueue * bcm43xx_setup_pioqueue(struct bcm43xx_private *bcm, - u16 pio_mmio_base) -{ - struct bcm43xx_pioqueue *queue; - u32 value; - u16 qsize; - - queue = kzalloc(sizeof(*queue), GFP_KERNEL); - if (!queue) - goto out; - - queue->bcm = bcm; - queue->mmio_base = pio_mmio_base; - queue->need_workarounds = (bcm->current_core->rev < 3); - - INIT_LIST_HEAD(&queue->txfree); - INIT_LIST_HEAD(&queue->txqueue); - INIT_LIST_HEAD(&queue->txrunning); - tasklet_init(&queue->txtask, tx_tasklet, - (unsigned long)queue); - - value = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - value &= ~BCM43xx_SBF_XFER_REG_BYTESWAP; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, value); - - qsize = bcm43xx_read16(bcm, queue->mmio_base + BCM43xx_PIO_TXQBUFSIZE); - if (qsize == 0) { - printk(KERN_ERR PFX "ERROR: This card does not support PIO " - "operation mode. Please use DMA mode " - "(module parameter pio=0).\n"); - goto err_freequeue; - } - if (qsize <= BCM43xx_PIO_TXQADJUST) { - printk(KERN_ERR PFX "PIO tx device-queue too small (%u)\n", - qsize); - goto err_freequeue; - } - qsize -= BCM43xx_PIO_TXQADJUST; - queue->tx_devq_size = qsize; - - setup_txqueues(queue); - -out: - return queue; - -err_freequeue: - kfree(queue); - queue = NULL; - goto out; -} - -static void cancel_transfers(struct bcm43xx_pioqueue *queue) -{ - struct bcm43xx_pio_txpacket *packet, *tmp_packet; - - netif_tx_disable(queue->bcm->net_dev); - tasklet_disable(&queue->txtask); - - list_for_each_entry_safe(packet, tmp_packet, &queue->txrunning, list) - free_txpacket(packet, 0); - list_for_each_entry_safe(packet, tmp_packet, &queue->txqueue, list) - free_txpacket(packet, 0); -} - -static void bcm43xx_destroy_pioqueue(struct bcm43xx_pioqueue *queue) -{ - if (!queue) - return; - - cancel_transfers(queue); - kfree(queue); -} - -void bcm43xx_pio_free(struct bcm43xx_private *bcm) -{ - struct bcm43xx_pio *pio; - - if (!bcm43xx_using_pio(bcm)) - return; - pio = bcm43xx_current_pio(bcm); - - bcm43xx_destroy_pioqueue(pio->queue3); - pio->queue3 = NULL; - bcm43xx_destroy_pioqueue(pio->queue2); - pio->queue2 = NULL; - bcm43xx_destroy_pioqueue(pio->queue1); - pio->queue1 = NULL; - bcm43xx_destroy_pioqueue(pio->queue0); - pio->queue0 = NULL; -} - -int bcm43xx_pio_init(struct bcm43xx_private *bcm) -{ - struct bcm43xx_pio *pio = bcm43xx_current_pio(bcm); - struct bcm43xx_pioqueue *queue; - int err = -ENOMEM; - - queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO1_BASE); - if (!queue) - goto out; - pio->queue0 = queue; - - queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO2_BASE); - if (!queue) - goto err_destroy0; - pio->queue1 = queue; - - queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO3_BASE); - if (!queue) - goto err_destroy1; - pio->queue2 = queue; - - queue = bcm43xx_setup_pioqueue(bcm, BCM43xx_MMIO_PIO4_BASE); - if (!queue) - goto err_destroy2; - pio->queue3 = queue; - - if (bcm->current_core->rev < 3) - bcm->irq_savedstate |= BCM43xx_IRQ_PIO_WORKAROUND; - - dprintk(KERN_INFO PFX "PIO initialized\n"); - err = 0; -out: - return err; - -err_destroy2: - bcm43xx_destroy_pioqueue(pio->queue2); - pio->queue2 = NULL; -err_destroy1: - bcm43xx_destroy_pioqueue(pio->queue1); - pio->queue1 = NULL; -err_destroy0: - bcm43xx_destroy_pioqueue(pio->queue0); - pio->queue0 = NULL; - goto out; -} - -int bcm43xx_pio_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - struct bcm43xx_pioqueue *queue = bcm43xx_current_pio(bcm)->queue1; - struct bcm43xx_pio_txpacket *packet; - - assert(!queue->tx_suspended); - assert(!list_empty(&queue->txfree)); - - packet = list_entry(queue->txfree.next, struct bcm43xx_pio_txpacket, list); - packet->txb = txb; - packet->xmitted_frags = 0; - packet->xmitted_octets = 0; - list_move_tail(&packet->list, &queue->txqueue); - queue->nr_txfree--; - assert(queue->nr_txfree < BCM43xx_PIO_MAXTXPACKETS); - - /* Suspend TX, if we are out of packets in the "free" queue. */ - if (list_empty(&queue->txfree)) { - netif_stop_queue(queue->bcm->net_dev); - queue->tx_suspended = 1; - } - - tasklet_schedule(&queue->txtask); - - return 0; -} - -void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ - struct bcm43xx_pioqueue *queue; - struct bcm43xx_pio_txpacket *packet; - - queue = parse_cookie(bcm, status->cookie, &packet); - assert(queue); - - free_txpacket(packet, 1); - if (queue->tx_suspended) { - queue->tx_suspended = 0; - netif_wake_queue(queue->bcm->net_dev); - } - /* If there are packets on the txqueue, poke the tasklet - * to transmit them. - */ - if (!list_empty(&queue->txqueue)) - tasklet_schedule(&queue->txtask); -} - -static void pio_rx_error(struct bcm43xx_pioqueue *queue, - int clear_buffers, - const char *error) -{ - int i; - - printkl("PIO RX error: %s\n", error); - bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, - BCM43xx_PIO_RXCTL_READY); - if (clear_buffers) { - assert(queue->mmio_base == BCM43xx_MMIO_PIO1_BASE); - for (i = 0; i < 15; i++) { - /* Dummy read. */ - bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - } - } -} - -void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) -{ - __le16 preamble[21] = { 0 }; - struct bcm43xx_rxhdr *rxhdr; - u16 tmp, len, rxflags2; - int i, preamble_readwords; - struct sk_buff *skb; - - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); - if (!(tmp & BCM43xx_PIO_RXCTL_DATAAVAILABLE)) - return; - bcm43xx_pio_write(queue, BCM43xx_PIO_RXCTL, - BCM43xx_PIO_RXCTL_DATAAVAILABLE); - - for (i = 0; i < 10; i++) { - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXCTL); - if (tmp & BCM43xx_PIO_RXCTL_READY) - goto data_ready; - udelay(10); - } - dprintkl(KERN_ERR PFX "PIO RX timed out\n"); - return; -data_ready: - - len = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - if (unlikely(len > 0x700)) { - pio_rx_error(queue, 0, "len > 0x700"); - return; - } - if (unlikely(len == 0 && queue->mmio_base != BCM43xx_MMIO_PIO4_BASE)) { - pio_rx_error(queue, 0, "len == 0"); - return; - } - preamble[0] = cpu_to_le16(len); - if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) - preamble_readwords = 14 / sizeof(u16); - else - preamble_readwords = 18 / sizeof(u16); - for (i = 0; i < preamble_readwords; i++) { - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - preamble[i + 1] = cpu_to_le16(tmp); - } - rxhdr = (struct bcm43xx_rxhdr *)preamble; - rxflags2 = le16_to_cpu(rxhdr->flags2); - if (unlikely(rxflags2 & BCM43xx_RXHDR_FLAGS2_INVALIDFRAME)) { - pio_rx_error(queue, - (queue->mmio_base == BCM43xx_MMIO_PIO1_BASE), - "invalid frame"); - return; - } - if (queue->mmio_base == BCM43xx_MMIO_PIO4_BASE) { - /* We received an xmit status. */ - struct bcm43xx_hwxmitstatus *hw; - struct bcm43xx_xmitstatus stat; - - hw = (struct bcm43xx_hwxmitstatus *)(preamble + 1); - stat.cookie = le16_to_cpu(hw->cookie); - stat.flags = hw->flags; - stat.cnt1 = hw->cnt1; - stat.cnt2 = hw->cnt2; - stat.seq = le16_to_cpu(hw->seq); - stat.unknown = le16_to_cpu(hw->unknown); - - bcm43xx_debugfs_log_txstat(queue->bcm, &stat); - bcm43xx_pio_handle_xmitstatus(queue->bcm, &stat); - - return; - } - - skb = dev_alloc_skb(len); - if (unlikely(!skb)) { - pio_rx_error(queue, 1, "OOM"); - return; - } - skb_put(skb, len); - for (i = 0; i < len - 1; i += 2) { - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - *((__le16 *)(skb->data + i)) = cpu_to_le16(tmp); - } - if (len % 2) { - tmp = bcm43xx_pio_read(queue, BCM43xx_PIO_RXDATA); - skb->data[len - 1] = (tmp & 0x00FF); -/* The specs say the following is required, but - * it is wrong and corrupts the PLCP. If we don't do - * this, the PLCP seems to be correct. So ifdef it out for now. - */ -#if 0 - if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) - skb->data[2] = (tmp & 0xFF00) >> 8; - else - skb->data[0] = (tmp & 0xFF00) >> 8; -#endif - } - skb_trim(skb, len - IEEE80211_FCS_LEN); - bcm43xx_rx(queue->bcm, skb, rxhdr); -} - -void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) -{ - bcm43xx_power_saving_ctl_bits(queue->bcm, -1, 1); - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) - | BCM43xx_PIO_TXCTL_SUSPEND); -} - -void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) -{ - bcm43xx_pio_write(queue, BCM43xx_PIO_TXCTL, - bcm43xx_pio_read(queue, BCM43xx_PIO_TXCTL) - & ~BCM43xx_PIO_TXCTL_SUSPEND); - bcm43xx_power_saving_ctl_bits(queue->bcm, -1, -1); - if (!list_empty(&queue->txqueue)) - tasklet_schedule(&queue->txtask); -} - -void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) -{ - struct bcm43xx_pio *pio; - - assert(bcm43xx_using_pio(bcm)); - pio = bcm43xx_current_pio(bcm); - pio->queue0->tx_frozen = 1; - pio->queue1->tx_frozen = 1; - pio->queue2->tx_frozen = 1; - pio->queue3->tx_frozen = 1; -} - -void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) -{ - struct bcm43xx_pio *pio; - - assert(bcm43xx_using_pio(bcm)); - pio = bcm43xx_current_pio(bcm); - pio->queue0->tx_frozen = 0; - pio->queue1->tx_frozen = 0; - pio->queue2->tx_frozen = 0; - pio->queue3->tx_frozen = 0; - if (!list_empty(&pio->queue0->txqueue)) - tasklet_schedule(&pio->queue0->txtask); - if (!list_empty(&pio->queue1->txqueue)) - tasklet_schedule(&pio->queue1->txtask); - if (!list_empty(&pio->queue2->txqueue)) - tasklet_schedule(&pio->queue2->txtask); - if (!list_empty(&pio->queue3->txqueue)) - tasklet_schedule(&pio->queue3->txtask); -} - - diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h b/drivers/net/wireless/bcm43xx/bcm43xx_pio.h deleted file mode 100644 index bc78a3c2cafb..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_pio.h +++ /dev/null @@ -1,163 +0,0 @@ -#ifndef BCM43xx_PIO_H_ -#define BCM43xx_PIO_H_ - -#include "bcm43xx.h" - -#include -#include -#include - - -#define BCM43xx_PIO_TXCTL 0x00 -#define BCM43xx_PIO_TXDATA 0x02 -#define BCM43xx_PIO_TXQBUFSIZE 0x04 -#define BCM43xx_PIO_RXCTL 0x08 -#define BCM43xx_PIO_RXDATA 0x0A - -#define BCM43xx_PIO_TXCTL_WRITELO (1 << 0) -#define BCM43xx_PIO_TXCTL_WRITEHI (1 << 1) -#define BCM43xx_PIO_TXCTL_COMPLETE (1 << 2) -#define BCM43xx_PIO_TXCTL_INIT (1 << 3) -#define BCM43xx_PIO_TXCTL_SUSPEND (1 << 7) - -#define BCM43xx_PIO_RXCTL_DATAAVAILABLE (1 << 0) -#define BCM43xx_PIO_RXCTL_READY (1 << 1) - -/* PIO constants */ -#define BCM43xx_PIO_MAXTXDEVQPACKETS 31 -#define BCM43xx_PIO_TXQADJUST 80 - -/* PIO tuning knobs */ -#define BCM43xx_PIO_MAXTXPACKETS 256 - - - -#ifdef CONFIG_BCM43XX_PIO - - -struct bcm43xx_pioqueue; -struct bcm43xx_xmitstatus; - -struct bcm43xx_pio_txpacket { - struct bcm43xx_pioqueue *queue; - struct ieee80211_txb *txb; - struct list_head list; - - u8 xmitted_frags; - u16 xmitted_octets; -}; - -#define pio_txpacket_getindex(packet) ((int)((packet) - (packet)->queue->tx_packets_cache)) - -struct bcm43xx_pioqueue { - struct bcm43xx_private *bcm; - u16 mmio_base; - - u8 tx_suspended:1, - tx_frozen:1, - need_workarounds:1; /* Workarounds needed for core.rev < 3 */ - - /* Adjusted size of the device internal TX buffer. */ - u16 tx_devq_size; - /* Used octets of the device internal TX buffer. */ - u16 tx_devq_used; - /* Used packet slots in the device internal TX buffer. */ - u8 tx_devq_packets; - /* Packets from the txfree list can - * be taken on incoming TX requests. - */ - struct list_head txfree; - unsigned int nr_txfree; - /* Packets on the txqueue are queued, - * but not completely written to the chip, yet. - */ - struct list_head txqueue; - /* Packets on the txrunning queue are completely - * posted to the device. We are waiting for the txstatus. - */ - struct list_head txrunning; - /* Total number or packets sent. - * (This counter can obviously wrap). - */ - unsigned int nr_tx_packets; - struct tasklet_struct txtask; - struct bcm43xx_pio_txpacket tx_packets_cache[BCM43xx_PIO_MAXTXPACKETS]; -}; - -static inline -u16 bcm43xx_pio_read(struct bcm43xx_pioqueue *queue, - u16 offset) -{ - return bcm43xx_read16(queue->bcm, queue->mmio_base + offset); -} - -static inline -void bcm43xx_pio_write(struct bcm43xx_pioqueue *queue, - u16 offset, u16 value) -{ - bcm43xx_write16(queue->bcm, queue->mmio_base + offset, value); - mmiowb(); -} - - -int bcm43xx_pio_init(struct bcm43xx_private *bcm); -void bcm43xx_pio_free(struct bcm43xx_private *bcm); - -int bcm43xx_pio_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb); -void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status); -void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue); - -/* Suspend a TX queue on hardware level. */ -void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue); -void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue); -/* Suspend (freeze) the TX tasklet (software level). */ -void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm); -void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm); - -#else /* CONFIG_BCM43XX_PIO */ - -static inline -int bcm43xx_pio_init(struct bcm43xx_private *bcm) -{ - return 0; -} -static inline -void bcm43xx_pio_free(struct bcm43xx_private *bcm) -{ -} -static inline -int bcm43xx_pio_tx(struct bcm43xx_private *bcm, - struct ieee80211_txb *txb) -{ - return 0; -} -static inline -void bcm43xx_pio_handle_xmitstatus(struct bcm43xx_private *bcm, - struct bcm43xx_xmitstatus *status) -{ -} -static inline -void bcm43xx_pio_rx(struct bcm43xx_pioqueue *queue) -{ -} -static inline -void bcm43xx_pio_tx_suspend(struct bcm43xx_pioqueue *queue) -{ -} -static inline -void bcm43xx_pio_tx_resume(struct bcm43xx_pioqueue *queue) -{ -} -static inline -void bcm43xx_pio_freeze_txqueues(struct bcm43xx_private *bcm) -{ -} -static inline -void bcm43xx_pio_thaw_txqueues(struct bcm43xx_private *bcm) -{ -} - -#endif /* CONFIG_BCM43XX_PIO */ -#endif /* BCM43xx_PIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.c b/drivers/net/wireless/bcm43xx/bcm43xx_power.c deleted file mode 100644 index 7e774f410953..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.c +++ /dev/null @@ -1,393 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include - -#include "bcm43xx.h" -#include "bcm43xx_power.h" -#include "bcm43xx_main.h" - - -/* Get the Slow Clock Source */ -static int bcm43xx_pctl_get_slowclksrc(struct bcm43xx_private *bcm) -{ - u32 tmp; - int err; - - assert(bcm->current_core == &bcm->core_chipcommon); - if (bcm->current_core->rev < 6) { - if (bcm->bustype == BCM43xx_BUSTYPE_PCMCIA || - bcm->bustype == BCM43xx_BUSTYPE_SB) - return BCM43xx_PCTL_CLKSRC_XTALOS; - if (bcm->bustype == BCM43xx_BUSTYPE_PCI) { - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &tmp); - assert(!err); - if (tmp & 0x10) - return BCM43xx_PCTL_CLKSRC_PCI; - return BCM43xx_PCTL_CLKSRC_XTALOS; - } - } - if (bcm->current_core->rev < 10) { - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - tmp &= 0x7; - if (tmp == 0) - return BCM43xx_PCTL_CLKSRC_LOPWROS; - if (tmp == 1) - return BCM43xx_PCTL_CLKSRC_XTALOS; - if (tmp == 2) - return BCM43xx_PCTL_CLKSRC_PCI; - } - - return BCM43xx_PCTL_CLKSRC_XTALOS; -} - -/* Get max/min slowclock frequency - * as described in http://bcm-specs.sipsolutions.net/PowerControl - */ -static int bcm43xx_pctl_clockfreqlimit(struct bcm43xx_private *bcm, - int get_max) -{ - int limit; - int clocksrc; - int divisor; - u32 tmp; - - assert(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL); - assert(bcm->current_core == &bcm->core_chipcommon); - - clocksrc = bcm43xx_pctl_get_slowclksrc(bcm); - if (bcm->current_core->rev < 6) { - switch (clocksrc) { - case BCM43xx_PCTL_CLKSRC_PCI: - divisor = 64; - break; - case BCM43xx_PCTL_CLKSRC_XTALOS: - divisor = 32; - break; - default: - assert(0); - divisor = 1; - } - } else if (bcm->current_core->rev < 10) { - switch (clocksrc) { - case BCM43xx_PCTL_CLKSRC_LOPWROS: - divisor = 1; - break; - case BCM43xx_PCTL_CLKSRC_XTALOS: - case BCM43xx_PCTL_CLKSRC_PCI: - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - divisor = ((tmp & 0xFFFF0000) >> 16) + 1; - divisor *= 4; - break; - default: - assert(0); - divisor = 1; - } - } else { - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL); - divisor = ((tmp & 0xFFFF0000) >> 16) + 1; - divisor *= 4; - } - - switch (clocksrc) { - case BCM43xx_PCTL_CLKSRC_LOPWROS: - if (get_max) - limit = 43000; - else - limit = 25000; - break; - case BCM43xx_PCTL_CLKSRC_XTALOS: - if (get_max) - limit = 20200000; - else - limit = 19800000; - break; - case BCM43xx_PCTL_CLKSRC_PCI: - if (get_max) - limit = 34000000; - else - limit = 25000000; - break; - default: - assert(0); - limit = 0; - } - limit /= divisor; - - return limit; -} - - -/* init power control - * as described in http://bcm-specs.sipsolutions.net/PowerControl - */ -int bcm43xx_pctl_init(struct bcm43xx_private *bcm) -{ - int err, maxfreq; - struct bcm43xx_coreinfo *old_core; - - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err == -ENODEV) - return 0; - if (err) - goto out; - - if (bcm->chip_id == 0x4321) { - if (bcm->chip_rev == 0) - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x03A4); - if (bcm->chip_rev == 1) - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_CTL, 0x00A4); - } - - if (bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) { - if (bcm->current_core->rev >= 10) { - /* Set Idle Power clock rate to 1Mhz */ - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL, - (bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SYSCLKCTL) - & 0x0000FFFF) | 0x40000); - } else { - maxfreq = bcm43xx_pctl_clockfreqlimit(bcm, 1); - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY, - (maxfreq * 150 + 999999) / 1000000); - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_FREFSELDELAY, - (maxfreq * 15 + 999999) / 1000000); - } - } - - err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - -out: - return err; -} - -u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm) -{ - u16 delay = 0; - int err; - u32 pll_on_delay; - struct bcm43xx_coreinfo *old_core; - int minfreq; - - if (bcm->bustype != BCM43xx_BUSTYPE_PCI) - goto out; - if (!(bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL)) - goto out; - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err == -ENODEV) - goto out; - - minfreq = bcm43xx_pctl_clockfreqlimit(bcm, 0); - pll_on_delay = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_PLLONDELAY); - delay = (((pll_on_delay + 2) * 1000000) + (minfreq - 1)) / minfreq; - - err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - -out: - return delay; -} - -/* set the powercontrol clock - * as described in http://bcm-specs.sipsolutions.net/PowerControl - */ -int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode) -{ - int err; - struct bcm43xx_coreinfo *old_core; - u32 tmp; - - old_core = bcm->current_core; - err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - if (err == -ENODEV) - return 0; - if (err) - goto out; - - if (bcm->core_chipcommon.rev < 6) { - if (mode == BCM43xx_PCTL_CLK_FAST) { - err = bcm43xx_pctl_set_crystal(bcm, 1); - if (err) - goto out; - } - } else { - if ((bcm->chipcommon_capabilities & BCM43xx_CAPABILITIES_PCTL) && - (bcm->core_chipcommon.rev < 10)) { - switch (mode) { - case BCM43xx_PCTL_CLK_FAST: - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - tmp = (tmp & ~BCM43xx_PCTL_FORCE_SLOW) | BCM43xx_PCTL_FORCE_PLL; - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); - break; - case BCM43xx_PCTL_CLK_SLOW: - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - tmp |= BCM43xx_PCTL_FORCE_SLOW; - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); - break; - case BCM43xx_PCTL_CLK_DYNAMIC: - tmp = bcm43xx_read32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL); - tmp &= ~BCM43xx_PCTL_FORCE_SLOW; - tmp |= BCM43xx_PCTL_FORCE_PLL; - tmp &= ~BCM43xx_PCTL_DYN_XTAL; - bcm43xx_write32(bcm, BCM43xx_CHIPCOMMON_SLOWCLKCTL, tmp); - } - } - } - - err = bcm43xx_switch_core(bcm, old_core); - assert(err == 0); - -out: - return err; -} - -int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on) -{ - int err; - u32 in, out, outenable; - - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_IN, &in); - if (err) - goto err_pci; - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUT, &out); - if (err) - goto err_pci; - err = bcm43xx_pci_read_config32(bcm, BCM43xx_PCTL_OUTENABLE, &outenable); - if (err) - goto err_pci; - - outenable |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN); - - if (on) { - if (in & 0x40) - return 0; - - out |= (BCM43xx_PCTL_XTAL_POWERUP | BCM43xx_PCTL_PLL_POWERDOWN); - - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); - if (err) - goto err_pci; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable); - if (err) - goto err_pci; - udelay(1000); - - out &= ~BCM43xx_PCTL_PLL_POWERDOWN; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); - if (err) - goto err_pci; - udelay(5000); - } else { - if (bcm->current_core->rev < 5) - return 0; - if (bcm->sprom.boardflags & BCM43xx_BFL_XTAL_NOSLOW) - return 0; - -/* XXX: Why BCM43xx_MMIO_RADIO_HWENABLED_xx can't be read at this time? - * err = bcm43xx_switch_core(bcm, bcm->active_80211_core); - * if (err) - * return err; - * if (((bcm->current_core->rev >= 3) && - * (bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) & (1 << 16))) || - * ((bcm->current_core->rev < 3) && - * !(bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) & (1 << 4)))) - * return 0; - * err = bcm43xx_switch_core(bcm, &bcm->core_chipcommon); - * if (err) - * return err; - */ - - err = bcm43xx_pctl_set_clock(bcm, BCM43xx_PCTL_CLK_SLOW); - if (err) - goto out; - out &= ~BCM43xx_PCTL_XTAL_POWERUP; - out |= BCM43xx_PCTL_PLL_POWERDOWN; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUT, out); - if (err) - goto err_pci; - err = bcm43xx_pci_write_config32(bcm, BCM43xx_PCTL_OUTENABLE, outenable); - if (err) - goto err_pci; - } - -out: - return err; - -err_pci: - printk(KERN_ERR PFX "Error: pctl_set_clock() could not access PCI config space!\n"); - err = -EBUSY; - goto out; -} - -/* Set the PowerSavingControlBits. - * Bitvalues: - * 0 => unset the bit - * 1 => set the bit - * -1 => calculate the bit - */ -void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm, - int bit25, int bit26) -{ - int i; - u32 status; - -//FIXME: Force 25 to off and 26 to on for now: -bit25 = 0; -bit26 = 1; - - if (bit25 == -1) { - //TODO: If powersave is not off and FIXME is not set and we are not in adhoc - // and thus is not an AP and we are associated, set bit 25 - } - if (bit26 == -1) { - //TODO: If the device is awake or this is an AP, or we are scanning, or FIXME, - // or we are associated, or FIXME, or the latest PS-Poll packet sent was - // successful, set bit26 - } - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - if (bit25) - status |= BCM43xx_SBF_PS1; - else - status &= ~BCM43xx_SBF_PS1; - if (bit26) - status |= BCM43xx_SBF_PS2; - else - status &= ~BCM43xx_SBF_PS2; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - if (bit26 && bcm->current_core->rev >= 5) { - for (i = 0; i < 100; i++) { - if (bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, 0x0040) != 4) - break; - udelay(10); - } - } -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_power.h b/drivers/net/wireless/bcm43xx/bcm43xx_power.h deleted file mode 100644 index c966ab3a5a8c..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_power.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_POWER_H_ -#define BCM43xx_POWER_H_ - -#include - -/* Clock sources */ -enum { - /* PCI clock */ - BCM43xx_PCTL_CLKSRC_PCI, - /* Crystal slow clock oscillator */ - BCM43xx_PCTL_CLKSRC_XTALOS, - /* Low power oscillator */ - BCM43xx_PCTL_CLKSRC_LOPWROS, -}; - -struct bcm43xx_private; - -int bcm43xx_pctl_init(struct bcm43xx_private *bcm); -int bcm43xx_pctl_set_clock(struct bcm43xx_private *bcm, u16 mode); -int bcm43xx_pctl_set_crystal(struct bcm43xx_private *bcm, int on); -u16 bcm43xx_pctl_powerup_delay(struct bcm43xx_private *bcm); - -void bcm43xx_power_saving_ctl_bits(struct bcm43xx_private *bcm, - int bit25, int bit26); - -#endif /* BCM43xx_POWER_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c b/drivers/net/wireless/bcm43xx/bcm43xx_radio.c deleted file mode 100644 index c605099c9baf..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.c +++ /dev/null @@ -1,2170 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include - -#include "bcm43xx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_phy.h" -#include "bcm43xx_radio.h" -#include "bcm43xx_ilt.h" - - -/* Table for bcm43xx_radio_calibrationvalue() */ -static const u16 rcc_table[16] = { - 0x0002, 0x0003, 0x0001, 0x000F, - 0x0006, 0x0007, 0x0005, 0x000F, - 0x000A, 0x000B, 0x0009, 0x000F, - 0x000E, 0x000F, 0x000D, 0x000F, -}; - -/* Reverse the bits of a 4bit value. - * Example: 1101 is flipped 1011 - */ -static u16 flip_4bit(u16 value) -{ - u16 flipped = 0x0000; - - assert((value & ~0x000F) == 0x0000); - - flipped |= (value & 0x0001) << 3; - flipped |= (value & 0x0002) << 1; - flipped |= (value & 0x0004) >> 1; - flipped |= (value & 0x0008) >> 3; - - return flipped; -} - -/* Get the freq, as it has to be written to the device. */ -static inline -u16 channel2freq_bg(u8 channel) -{ - /* Frequencies are given as frequencies_bg[index] + 2.4GHz - * Starting with channel 1 - */ - static const u16 frequencies_bg[14] = { - 12, 17, 22, 27, - 32, 37, 42, 47, - 52, 57, 62, 67, - 72, 84, - }; - - assert(channel >= 1 && channel <= 14); - - return frequencies_bg[channel - 1]; -} - -/* Get the freq, as it has to be written to the device. */ -static inline -u16 channel2freq_a(u8 channel) -{ - assert(channel <= 200); - - return (5000 + 5 * channel); -} - -void bcm43xx_radio_lock(struct bcm43xx_private *bcm) -{ - u32 status; - - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status |= BCM43xx_SBF_RADIOREG_LOCK; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - mmiowb(); - udelay(10); -} - -void bcm43xx_radio_unlock(struct bcm43xx_private *bcm) -{ - u32 status; - - bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_VER); /* dummy read */ - status = bcm43xx_read32(bcm, BCM43xx_MMIO_STATUS_BITFIELD); - status &= ~BCM43xx_SBF_RADIOREG_LOCK; - bcm43xx_write32(bcm, BCM43xx_MMIO_STATUS_BITFIELD, status); - mmiowb(); -} - -u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - offset |= 0x0040; - break; - case BCM43xx_PHYTYPE_B: - if (radio->version == 0x2053) { - if (offset < 0x70) - offset += 0x80; - else if (offset < 0x80) - offset += 0x70; - } else if (radio->version == 0x2050) { - offset |= 0x80; - } else - assert(0); - break; - case BCM43xx_PHYTYPE_G: - offset |= 0x80; - break; - } - - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); - return bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW); -} - -void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val) -{ - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_CONTROL, offset); - mmiowb(); - bcm43xx_write16(bcm, BCM43xx_MMIO_RADIO_DATA_LOW, val); -} - -static void bcm43xx_set_all_gains(struct bcm43xx_private *bcm, - s16 first, s16 second, s16 third) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 i; - u16 start = 0x08, end = 0x18; - u16 offset = 0x0400; - u16 tmp; - - if (phy->rev <= 1) { - offset = 0x5000; - start = 0x10; - end = 0x20; - } - - for (i = 0; i < 4; i++) - bcm43xx_ilt_write(bcm, offset + i, first); - - for (i = start; i < end; i++) - bcm43xx_ilt_write(bcm, offset + i, second); - - if (third != -1) { - tmp = ((u16)third << 14) | ((u16)third << 6); - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | tmp); - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | tmp); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | tmp); - } - bcm43xx_dummy_transmission(bcm); -} - -static void bcm43xx_set_original_gains(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 i, tmp; - u16 offset = 0x0400; - u16 start = 0x0008, end = 0x0018; - - if (phy->rev <= 1) { - offset = 0x5000; - start = 0x0010; - end = 0x0020; - } - - for (i = 0; i < 4; i++) { - tmp = (i & 0xFFFC); - tmp |= (i & 0x0001) << 1; - tmp |= (i & 0x0002) >> 1; - - bcm43xx_ilt_write(bcm, offset + i, tmp); - } - - for (i = start; i < end; i++) - bcm43xx_ilt_write(bcm, offset + i, i - start); - - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xBFBF) | 0x4040); - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xBFBF) | 0x4040); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xBFBF) | 0x4000); - bcm43xx_dummy_transmission(bcm); -} - -/* Synthetic PU workaround */ -static void bcm43xx_synth_pu_workaround(struct bcm43xx_private *bcm, u8 channel) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - if (radio->version != 0x2050 || radio->revision >= 6) { - /* We do not need the workaround. */ - return; - } - - if (channel <= 10) { - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, - channel2freq_bg(channel + 4)); - } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, - channel2freq_bg(1)); - } - udelay(100); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, - channel2freq_bg(channel)); -} - -u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u8 ret = 0; - u16 saved, rssi, temp; - int i, j = 0; - - saved = bcm43xx_phy_read(bcm, 0x0403); - bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_phy_write(bcm, 0x0403, (saved & 0xFFF8) | 5); - if (radio->aci_hw_rssi) - rssi = bcm43xx_phy_read(bcm, 0x048A) & 0x3F; - else - rssi = saved & 0x3F; - /* clamp temp to signed 5bit */ - if (rssi > 32) - rssi -= 64; - for (i = 0;i < 100; i++) { - temp = (bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x3F; - if (temp > 32) - temp -= 64; - if (temp < rssi) - j++; - if (j >= 20) - ret = 1; - } - bcm43xx_phy_write(bcm, 0x0403, saved); - - return ret; -} - -u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u8 ret[13]; - unsigned int channel = radio->channel; - unsigned int i, j, start, end; - unsigned long phylock_flags; - - if (!((phy->type == BCM43xx_PHYTYPE_G) && (phy->rev > 0))) - return 0; - - bcm43xx_phy_lock(bcm, phylock_flags); - bcm43xx_radio_lock(bcm); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF); - bcm43xx_set_all_gains(bcm, 3, 8, 1); - - start = (channel - 5 > 0) ? channel - 5 : 1; - end = (channel + 5 < 14) ? channel + 5 : 13; - - for (i = start; i <= end; i++) { - if (abs(channel - i) > 2) - ret[i-1] = bcm43xx_radio_aci_detect(bcm, i); - } - bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_phy_write(bcm, 0x0802, - (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC) | 0x0003); - bcm43xx_phy_write(bcm, 0x0403, - bcm43xx_phy_read(bcm, 0x0403) & 0xFFF8); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); - bcm43xx_set_original_gains(bcm); - for (i = 0; i < 13; i++) { - if (!ret[i]) - continue; - end = (i + 5 < 13) ? i + 5 : 13; - for (j = i; j < end; j++) - ret[j] = 1; - } - bcm43xx_radio_unlock(bcm); - bcm43xx_phy_unlock(bcm, phylock_flags); - - return ret[channel - 1]; -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val) -{ - bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); - mmiowb(); - bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_DATA, (u16)val); -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset) -{ - u16 val; - - bcm43xx_phy_write(bcm, BCM43xx_PHY_NRSSILT_CTRL, offset); - val = bcm43xx_phy_read(bcm, BCM43xx_PHY_NRSSILT_DATA); - - return (s16)val; -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val) -{ - u16 i; - s16 tmp; - - for (i = 0; i < 64; i++) { - tmp = bcm43xx_nrssi_hw_read(bcm, i); - tmp -= val; - tmp = limit_value(tmp, -32, 31); - bcm43xx_nrssi_hw_write(bcm, i, tmp); - } -} - -/* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ -void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - s16 i, delta; - s32 tmp; - - delta = 0x1F - radio->nrssi[0]; - for (i = 0; i < 64; i++) { - tmp = (i - delta) * radio->nrssislope; - tmp /= 0x10000; - tmp += 0x3A; - tmp = limit_value(tmp, 0, 0x3F); - radio->nrssi_lt[i] = tmp; - } -} - -static void bcm43xx_calc_nrssi_offset(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - u16 backup[20] = { 0 }; - s16 v47F; - u16 i; - u16 saved = 0xFFFF; - - backup[0] = bcm43xx_phy_read(bcm, 0x0001); - backup[1] = bcm43xx_phy_read(bcm, 0x0811); - backup[2] = bcm43xx_phy_read(bcm, 0x0812); - backup[3] = bcm43xx_phy_read(bcm, 0x0814); - backup[4] = bcm43xx_phy_read(bcm, 0x0815); - backup[5] = bcm43xx_phy_read(bcm, 0x005A); - backup[6] = bcm43xx_phy_read(bcm, 0x0059); - backup[7] = bcm43xx_phy_read(bcm, 0x0058); - backup[8] = bcm43xx_phy_read(bcm, 0x000A); - backup[9] = bcm43xx_phy_read(bcm, 0x0003); - backup[10] = bcm43xx_radio_read16(bcm, 0x007A); - backup[11] = bcm43xx_radio_read16(bcm, 0x0043); - - bcm43xx_phy_write(bcm, 0x0429, - bcm43xx_phy_read(bcm, 0x0429) & 0x7FFF); - bcm43xx_phy_write(bcm, 0x0001, - (bcm43xx_phy_read(bcm, 0x0001) & 0x3FFF) | 0x4000); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x000C); - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) & 0xFFF3) | 0x0004); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) & ~(0x1 | 0x2)); - if (phy->rev >= 6) { - backup[12] = bcm43xx_phy_read(bcm, 0x002E); - backup[13] = bcm43xx_phy_read(bcm, 0x002F); - backup[14] = bcm43xx_phy_read(bcm, 0x080F); - backup[15] = bcm43xx_phy_read(bcm, 0x0810); - backup[16] = bcm43xx_phy_read(bcm, 0x0801); - backup[17] = bcm43xx_phy_read(bcm, 0x0060); - backup[18] = bcm43xx_phy_read(bcm, 0x0014); - backup[19] = bcm43xx_phy_read(bcm, 0x0478); - - bcm43xx_phy_write(bcm, 0x002E, 0); - bcm43xx_phy_write(bcm, 0x002F, 0); - bcm43xx_phy_write(bcm, 0x080F, 0); - bcm43xx_phy_write(bcm, 0x0810, 0); - bcm43xx_phy_write(bcm, 0x0478, - bcm43xx_phy_read(bcm, 0x0478) | 0x0100); - bcm43xx_phy_write(bcm, 0x0801, - bcm43xx_phy_read(bcm, 0x0801) | 0x0040); - bcm43xx_phy_write(bcm, 0x0060, - bcm43xx_phy_read(bcm, 0x0060) | 0x0040); - bcm43xx_phy_write(bcm, 0x0014, - bcm43xx_phy_read(bcm, 0x0014) | 0x0200); - } - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); - udelay(30); - - v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F == 31) { - for (i = 7; i >= 4; i--) { - bcm43xx_radio_write16(bcm, 0x007B, i); - udelay(20); - v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F < 31 && saved == 0xFFFF) - saved = i; - } - if (saved == 0xFFFF) - saved = 4; - } else { - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0001); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFE); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x000C); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) | 0x000C); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) | 0x0030); - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) | 0x0030); - bcm43xx_phy_write(bcm, 0x005A, 0x0480); - bcm43xx_phy_write(bcm, 0x0059, 0x0810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->analog == 0) { - bcm43xx_phy_write(bcm, 0x0003, 0x0122); - } else { - bcm43xx_phy_write(bcm, 0x000A, - bcm43xx_phy_read(bcm, 0x000A) - | 0x2000); - } - bcm43xx_phy_write(bcm, 0x0814, - bcm43xx_phy_read(bcm, 0x0814) | 0x0004); - bcm43xx_phy_write(bcm, 0x0815, - bcm43xx_phy_read(bcm, 0x0815) & 0xFFFB); - bcm43xx_phy_write(bcm, 0x0003, - (bcm43xx_phy_read(bcm, 0x0003) & 0xFF9F) - | 0x0040); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); - bcm43xx_set_all_gains(bcm, 3, 0, 1); - bcm43xx_radio_write16(bcm, 0x0043, - (bcm43xx_radio_read16(bcm, 0x0043) - & 0x00F0) | 0x000F); - udelay(30); - v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F == -32) { - for (i = 0; i < 4; i++) { - bcm43xx_radio_write16(bcm, 0x007B, i); - udelay(20); - v47F = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (v47F >= 0x20) - v47F -= 0x40; - if (v47F > -31 && saved == 0xFFFF) - saved = i; - } - if (saved == 0xFFFF) - saved = 3; - } else - saved = 0; - } - bcm43xx_radio_write16(bcm, 0x007B, saved); - - if (phy->rev >= 6) { - bcm43xx_phy_write(bcm, 0x002E, backup[12]); - bcm43xx_phy_write(bcm, 0x002F, backup[13]); - bcm43xx_phy_write(bcm, 0x080F, backup[14]); - bcm43xx_phy_write(bcm, 0x0810, backup[15]); - } - bcm43xx_phy_write(bcm, 0x0814, backup[3]); - bcm43xx_phy_write(bcm, 0x0815, backup[4]); - bcm43xx_phy_write(bcm, 0x005A, backup[5]); - bcm43xx_phy_write(bcm, 0x0059, backup[6]); - bcm43xx_phy_write(bcm, 0x0058, backup[7]); - bcm43xx_phy_write(bcm, 0x000A, backup[8]); - bcm43xx_phy_write(bcm, 0x0003, backup[9]); - bcm43xx_radio_write16(bcm, 0x0043, backup[11]); - bcm43xx_radio_write16(bcm, 0x007A, backup[10]); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) | 0x1 | 0x2); - bcm43xx_phy_write(bcm, 0x0429, - bcm43xx_phy_read(bcm, 0x0429) | 0x8000); - bcm43xx_set_original_gains(bcm); - if (phy->rev >= 6) { - bcm43xx_phy_write(bcm, 0x0801, backup[16]); - bcm43xx_phy_write(bcm, 0x0060, backup[17]); - bcm43xx_phy_write(bcm, 0x0014, backup[18]); - bcm43xx_phy_write(bcm, 0x0478, backup[19]); - } - bcm43xx_phy_write(bcm, 0x0001, backup[0]); - bcm43xx_phy_write(bcm, 0x0812, backup[2]); - bcm43xx_phy_write(bcm, 0x0811, backup[1]); -} - -void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup[18] = { 0 }; - u16 tmp; - s16 nrssi0, nrssi1; - - switch (phy->type) { - case BCM43xx_PHYTYPE_B: - backup[0] = bcm43xx_radio_read16(bcm, 0x007A); - backup[1] = bcm43xx_radio_read16(bcm, 0x0052); - backup[2] = bcm43xx_radio_read16(bcm, 0x0043); - backup[3] = bcm43xx_phy_read(bcm, 0x0030); - backup[4] = bcm43xx_phy_read(bcm, 0x0026); - backup[5] = bcm43xx_phy_read(bcm, 0x0015); - backup[6] = bcm43xx_phy_read(bcm, 0x002A); - backup[7] = bcm43xx_phy_read(bcm, 0x0020); - backup[8] = bcm43xx_phy_read(bcm, 0x005A); - backup[9] = bcm43xx_phy_read(bcm, 0x0059); - backup[10] = bcm43xx_phy_read(bcm, 0x0058); - backup[11] = bcm43xx_read16(bcm, 0x03E2); - backup[12] = bcm43xx_read16(bcm, 0x03E6); - backup[13] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); - - tmp = bcm43xx_radio_read16(bcm, 0x007A); - tmp &= (phy->rev >= 5) ? 0x007F : 0x000F; - bcm43xx_radio_write16(bcm, 0x007A, tmp); - bcm43xx_phy_write(bcm, 0x0030, 0x00FF); - bcm43xx_write16(bcm, 0x03EC, 0x7F7F); - bcm43xx_phy_write(bcm, 0x0026, 0x0000); - bcm43xx_phy_write(bcm, 0x0015, - bcm43xx_phy_read(bcm, 0x0015) | 0x0020); - bcm43xx_phy_write(bcm, 0x002A, 0x08A3); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); - - nrssi0 = (s16)bcm43xx_phy_read(bcm, 0x0027); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->analog >= 2) { - bcm43xx_write16(bcm, 0x03E6, 0x0040); - } else if (phy->analog == 0) { - bcm43xx_write16(bcm, 0x03E6, 0x0122); - } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) & 0x2000); - } - bcm43xx_phy_write(bcm, 0x0020, 0x3F3F); - bcm43xx_phy_write(bcm, 0x0015, 0xF330); - bcm43xx_radio_write16(bcm, 0x005A, 0x0060); - bcm43xx_radio_write16(bcm, 0x0043, - bcm43xx_radio_read16(bcm, 0x0043) & 0x00F0); - bcm43xx_phy_write(bcm, 0x005A, 0x0480); - bcm43xx_phy_write(bcm, 0x0059, 0x0810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - udelay(20); - - nrssi1 = (s16)bcm43xx_phy_read(bcm, 0x0027); - bcm43xx_phy_write(bcm, 0x0030, backup[3]); - bcm43xx_radio_write16(bcm, 0x007A, backup[0]); - bcm43xx_write16(bcm, 0x03E2, backup[11]); - bcm43xx_phy_write(bcm, 0x0026, backup[4]); - bcm43xx_phy_write(bcm, 0x0015, backup[5]); - bcm43xx_phy_write(bcm, 0x002A, backup[6]); - bcm43xx_synth_pu_workaround(bcm, radio->channel); - if (phy->analog != 0) - bcm43xx_write16(bcm, 0x03F4, backup[13]); - - bcm43xx_phy_write(bcm, 0x0020, backup[7]); - bcm43xx_phy_write(bcm, 0x005A, backup[8]); - bcm43xx_phy_write(bcm, 0x0059, backup[9]); - bcm43xx_phy_write(bcm, 0x0058, backup[10]); - bcm43xx_radio_write16(bcm, 0x0052, backup[1]); - bcm43xx_radio_write16(bcm, 0x0043, backup[2]); - - if (nrssi0 == nrssi1) - radio->nrssislope = 0x00010000; - else - radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); - - if (nrssi0 <= -4) { - radio->nrssi[0] = nrssi0; - radio->nrssi[1] = nrssi1; - } - break; - case BCM43xx_PHYTYPE_G: - if (radio->revision >= 9) - return; - if (radio->revision == 8) - bcm43xx_calc_nrssi_offset(bcm); - - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & 0x7FFF); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC); - backup[7] = bcm43xx_read16(bcm, 0x03E2); - bcm43xx_write16(bcm, 0x03E2, - bcm43xx_read16(bcm, 0x03E2) | 0x8000); - backup[0] = bcm43xx_radio_read16(bcm, 0x007A); - backup[1] = bcm43xx_radio_read16(bcm, 0x0052); - backup[2] = bcm43xx_radio_read16(bcm, 0x0043); - backup[3] = bcm43xx_phy_read(bcm, 0x0015); - backup[4] = bcm43xx_phy_read(bcm, 0x005A); - backup[5] = bcm43xx_phy_read(bcm, 0x0059); - backup[6] = bcm43xx_phy_read(bcm, 0x0058); - backup[8] = bcm43xx_read16(bcm, 0x03E6); - backup[9] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); - if (phy->rev >= 3) { - backup[10] = bcm43xx_phy_read(bcm, 0x002E); - backup[11] = bcm43xx_phy_read(bcm, 0x002F); - backup[12] = bcm43xx_phy_read(bcm, 0x080F); - backup[13] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_LO_CONTROL); - backup[14] = bcm43xx_phy_read(bcm, 0x0801); - backup[15] = bcm43xx_phy_read(bcm, 0x0060); - backup[16] = bcm43xx_phy_read(bcm, 0x0014); - backup[17] = bcm43xx_phy_read(bcm, 0x0478); - bcm43xx_phy_write(bcm, 0x002E, 0); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, 0); - switch (phy->rev) { - case 4: case 6: case 7: - bcm43xx_phy_write(bcm, 0x0478, - bcm43xx_phy_read(bcm, 0x0478) - | 0x0100); - bcm43xx_phy_write(bcm, 0x0801, - bcm43xx_phy_read(bcm, 0x0801) - | 0x0040); - break; - case 3: case 5: - bcm43xx_phy_write(bcm, 0x0801, - bcm43xx_phy_read(bcm, 0x0801) - & 0xFFBF); - break; - } - bcm43xx_phy_write(bcm, 0x0060, - bcm43xx_phy_read(bcm, 0x0060) - | 0x0040); - bcm43xx_phy_write(bcm, 0x0014, - bcm43xx_phy_read(bcm, 0x0014) - | 0x0200); - } - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0070); - bcm43xx_set_all_gains(bcm, 0, 8, 0); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) & 0x00F7); - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0811, - (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0030); - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0010); - } - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x0080); - udelay(20); - - nrssi0 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (nrssi0 >= 0x0020) - nrssi0 -= 0x0040; - - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) & 0x007F); - if (phy->analog >= 2) { - bcm43xx_phy_write(bcm, 0x0003, - (bcm43xx_phy_read(bcm, 0x0003) - & 0xFF9F) | 0x0040); - } - - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) - | 0x2000); - bcm43xx_radio_write16(bcm, 0x007A, - bcm43xx_radio_read16(bcm, 0x007A) | 0x000F); - bcm43xx_phy_write(bcm, 0x0015, 0xF330); - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0812, - (bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF) | 0x0020); - bcm43xx_phy_write(bcm, 0x0811, - (bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF) | 0x0020); - } - - bcm43xx_set_all_gains(bcm, 3, 0, 1); - if (radio->revision == 8) { - bcm43xx_radio_write16(bcm, 0x0043, 0x001F); - } else { - tmp = bcm43xx_radio_read16(bcm, 0x0052) & 0xFF0F; - bcm43xx_radio_write16(bcm, 0x0052, tmp | 0x0060); - tmp = bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0; - bcm43xx_radio_write16(bcm, 0x0043, tmp | 0x0009); - } - bcm43xx_phy_write(bcm, 0x005A, 0x0480); - bcm43xx_phy_write(bcm, 0x0059, 0x0810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - udelay(20); - nrssi1 = (s16)((bcm43xx_phy_read(bcm, 0x047F) >> 8) & 0x003F); - if (nrssi1 >= 0x0020) - nrssi1 -= 0x0040; - if (nrssi0 == nrssi1) - radio->nrssislope = 0x00010000; - else - radio->nrssislope = 0x00400000 / (nrssi0 - nrssi1); - if (nrssi0 >= -4) { - radio->nrssi[0] = nrssi1; - radio->nrssi[1] = nrssi0; - } - if (phy->rev >= 3) { - bcm43xx_phy_write(bcm, 0x002E, backup[10]); - bcm43xx_phy_write(bcm, 0x002F, backup[11]); - bcm43xx_phy_write(bcm, 0x080F, backup[12]); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_LO_CONTROL, backup[13]); - } - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_phy_read(bcm, 0x0812) & 0xFFCF); - bcm43xx_phy_write(bcm, 0x0811, - bcm43xx_phy_read(bcm, 0x0811) & 0xFFCF); - } - - bcm43xx_radio_write16(bcm, 0x007A, backup[0]); - bcm43xx_radio_write16(bcm, 0x0052, backup[1]); - bcm43xx_radio_write16(bcm, 0x0043, backup[2]); - bcm43xx_write16(bcm, 0x03E2, backup[7]); - bcm43xx_write16(bcm, 0x03E6, backup[8]); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[9]); - bcm43xx_phy_write(bcm, 0x0015, backup[3]); - bcm43xx_phy_write(bcm, 0x005A, backup[4]); - bcm43xx_phy_write(bcm, 0x0059, backup[5]); - bcm43xx_phy_write(bcm, 0x0058, backup[6]); - bcm43xx_synth_pu_workaround(bcm, radio->channel); - bcm43xx_phy_write(bcm, 0x0802, - bcm43xx_phy_read(bcm, 0x0802) | (0x0001 | 0x0002)); - bcm43xx_set_original_gains(bcm); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x8000); - if (phy->rev >= 3) { - bcm43xx_phy_write(bcm, 0x0801, backup[14]); - bcm43xx_phy_write(bcm, 0x0060, backup[15]); - bcm43xx_phy_write(bcm, 0x0014, backup[16]); - bcm43xx_phy_write(bcm, 0x0478, backup[17]); - } - bcm43xx_nrssi_mem_update(bcm); - bcm43xx_calc_nrssi_threshold(bcm); - break; - default: - assert(0); - } -} - -void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - s32 threshold; - s32 a, b; - s16 tmp16; - u16 tmp_u16; - - switch (phy->type) { - case BCM43xx_PHYTYPE_B: { - if (radio->version != 0x2050) - return; - if (!(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) - return; - - if (radio->revision >= 6) { - threshold = (radio->nrssi[1] - radio->nrssi[0]) * 32; - threshold += 20 * (radio->nrssi[0] + 1); - threshold /= 40; - } else - threshold = radio->nrssi[1] - 5; - - threshold = limit_value(threshold, 0, 0x3E); - bcm43xx_phy_read(bcm, 0x0020); /* dummy read */ - bcm43xx_phy_write(bcm, 0x0020, (((u16)threshold) << 8) | 0x001C); - - if (radio->revision >= 6) { - bcm43xx_phy_write(bcm, 0x0087, 0x0E0D); - bcm43xx_phy_write(bcm, 0x0086, 0x0C0B); - bcm43xx_phy_write(bcm, 0x0085, 0x0A09); - bcm43xx_phy_write(bcm, 0x0084, 0x0808); - bcm43xx_phy_write(bcm, 0x0083, 0x0808); - bcm43xx_phy_write(bcm, 0x0082, 0x0604); - bcm43xx_phy_write(bcm, 0x0081, 0x0302); - bcm43xx_phy_write(bcm, 0x0080, 0x0100); - } - break; - } - case BCM43xx_PHYTYPE_G: - if (!phy->connected || - !(bcm->sprom.boardflags & BCM43xx_BFL_RSSI)) { - tmp16 = bcm43xx_nrssi_hw_read(bcm, 0x20); - if (tmp16 >= 0x20) - tmp16 -= 0x40; - if (tmp16 < 3) { - bcm43xx_phy_write(bcm, 0x048A, - (bcm43xx_phy_read(bcm, 0x048A) - & 0xF000) | 0x09EB); - } else { - bcm43xx_phy_write(bcm, 0x048A, - (bcm43xx_phy_read(bcm, 0x048A) - & 0xF000) | 0x0AED); - } - } else { - if (radio->interfmode == BCM43xx_RADIO_INTERFMODE_NONWLAN) { - a = 0xE; - b = 0xA; - } else if (!radio->aci_wlan_automatic && radio->aci_enable) { - a = 0x13; - b = 0x12; - } else { - a = 0xE; - b = 0x11; - } - - a = a * (radio->nrssi[1] - radio->nrssi[0]); - a += (radio->nrssi[0] << 6); - if (a < 32) - a += 31; - else - a += 32; - a = a >> 6; - a = limit_value(a, -31, 31); - - b = b * (radio->nrssi[1] - radio->nrssi[0]); - b += (radio->nrssi[0] << 6); - if (b < 32) - b += 31; - else - b += 32; - b = b >> 6; - b = limit_value(b, -31, 31); - - tmp_u16 = bcm43xx_phy_read(bcm, 0x048A) & 0xF000; - tmp_u16 |= ((u32)b & 0x0000003F); - tmp_u16 |= (((u32)a & 0x0000003F) << 6); - bcm43xx_phy_write(bcm, 0x048A, tmp_u16); - } - break; - default: - assert(0); - } -} - -/* Stack implementation to save/restore values from the - * interference mitigation code. - * It is save to restore values in random order. - */ -static void _stack_save(u32 *_stackptr, size_t *stackidx, - u8 id, u16 offset, u16 value) -{ - u32 *stackptr = &(_stackptr[*stackidx]); - - assert((offset & 0xE000) == 0x0000); - assert((id & 0xF8) == 0x00); - *stackptr = offset; - *stackptr |= ((u32)id) << 13; - *stackptr |= ((u32)value) << 16; - (*stackidx)++; - assert(*stackidx < BCM43xx_INTERFSTACK_SIZE); -} - -static u16 _stack_restore(u32 *stackptr, - u8 id, u16 offset) -{ - size_t i; - - assert((offset & 0xE000) == 0x0000); - assert((id & 0xF8) == 0x00); - for (i = 0; i < BCM43xx_INTERFSTACK_SIZE; i++, stackptr++) { - if ((*stackptr & 0x00001FFF) != offset) - continue; - if (((*stackptr & 0x00007000) >> 13) != id) - continue; - return ((*stackptr & 0xFFFF0000) >> 16); - } - assert(0); - - return 0; -} - -#define phy_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x1, (offset), \ - bcm43xx_phy_read(bcm, (offset))); \ - } while (0) -#define phy_stackrestore(offset) \ - do { \ - bcm43xx_phy_write(bcm, (offset), \ - _stack_restore(stack, 0x1, \ - (offset))); \ - } while (0) -#define radio_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x2, (offset), \ - bcm43xx_radio_read16(bcm, (offset))); \ - } while (0) -#define radio_stackrestore(offset) \ - do { \ - bcm43xx_radio_write16(bcm, (offset), \ - _stack_restore(stack, 0x2, \ - (offset))); \ - } while (0) -#define ilt_stacksave(offset) \ - do { \ - _stack_save(stack, &stackidx, 0x3, (offset), \ - bcm43xx_ilt_read(bcm, (offset))); \ - } while (0) -#define ilt_stackrestore(offset) \ - do { \ - bcm43xx_ilt_write(bcm, (offset), \ - _stack_restore(stack, 0x3, \ - (offset))); \ - } while (0) - -static void -bcm43xx_radio_interference_mitigation_enable(struct bcm43xx_private *bcm, - int mode) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 tmp, flipped; - u32 tmp32; - size_t stackidx = 0; - u32 *stack = radio->interfstack; - - switch (mode) { - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) | 0x0800); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) & ~0x4000); - break; - } - radio_stacksave(0x0078); - tmp = (bcm43xx_radio_read16(bcm, 0x0078) & 0x001E); - flipped = flip_4bit(tmp); - if (flipped < 10 && flipped >= 8) - flipped = 7; - else if (flipped >= 10) - flipped -= 3; - flipped = flip_4bit(flipped); - flipped = (flipped << 1) | 0x0020; - bcm43xx_radio_write16(bcm, 0x0078, flipped); - - bcm43xx_calc_nrssi_threshold(bcm); - - phy_stacksave(0x0406); - bcm43xx_phy_write(bcm, 0x0406, 0x7E28); - - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) | 0x0800); - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) | 0x1000); - - phy_stacksave(0x04A0); - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) & 0xC0C0) | 0x0008); - phy_stacksave(0x04A1); - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) & 0xC0C0) | 0x0605); - phy_stacksave(0x04A2); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) & 0xC0C0) | 0x0204); - phy_stacksave(0x04A8); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) & 0xC0C0) | 0x0803); - phy_stacksave(0x04AB); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) & 0xC0C0) | 0x0605); - - phy_stacksave(0x04A7); - bcm43xx_phy_write(bcm, 0x04A7, 0x0002); - phy_stacksave(0x04A3); - bcm43xx_phy_write(bcm, 0x04A3, 0x287A); - phy_stacksave(0x04A9); - bcm43xx_phy_write(bcm, 0x04A9, 0x2027); - phy_stacksave(0x0493); - bcm43xx_phy_write(bcm, 0x0493, 0x32F5); - phy_stacksave(0x04AA); - bcm43xx_phy_write(bcm, 0x04AA, 0x2027); - phy_stacksave(0x04AC); - bcm43xx_phy_write(bcm, 0x04AC, 0x32F5); - break; - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - if (bcm43xx_phy_read(bcm, 0x0033) & 0x0800) - break; - - radio->aci_enable = 1; - - phy_stacksave(BCM43xx_PHY_RADIO_BITFIELD); - phy_stacksave(BCM43xx_PHY_G_CRS); - if (phy->rev < 2) { - phy_stacksave(0x0406); - } else { - phy_stacksave(0x04C0); - phy_stacksave(0x04C1); - } - phy_stacksave(0x0033); - phy_stacksave(0x04A7); - phy_stacksave(0x04A3); - phy_stacksave(0x04A9); - phy_stacksave(0x04AA); - phy_stacksave(0x04AC); - phy_stacksave(0x0493); - phy_stacksave(0x04A1); - phy_stacksave(0x04A0); - phy_stacksave(0x04A2); - phy_stacksave(0x048A); - phy_stacksave(0x04A8); - phy_stacksave(0x04AB); - if (phy->rev == 2) { - phy_stacksave(0x04AD); - phy_stacksave(0x04AE); - } else if (phy->rev >= 3) { - phy_stacksave(0x04AD); - phy_stacksave(0x0415); - phy_stacksave(0x0416); - phy_stacksave(0x0417); - ilt_stacksave(0x1A00 + 0x2); - ilt_stacksave(0x1A00 + 0x3); - } - phy_stacksave(0x042B); - phy_stacksave(0x048C); - - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) - & ~0x1000); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) - & 0xFFFC) | 0x0002); - - bcm43xx_phy_write(bcm, 0x0033, 0x0800); - bcm43xx_phy_write(bcm, 0x04A3, 0x2027); - bcm43xx_phy_write(bcm, 0x04A9, 0x1CA8); - bcm43xx_phy_write(bcm, 0x0493, 0x287A); - bcm43xx_phy_write(bcm, 0x04AA, 0x1CA8); - bcm43xx_phy_write(bcm, 0x04AC, 0x287A); - - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) - & 0xFFC0) | 0x001A); - bcm43xx_phy_write(bcm, 0x04A7, 0x000D); - - if (phy->rev < 2) { - bcm43xx_phy_write(bcm, 0x0406, 0xFF0D); - } else if (phy->rev == 2) { - bcm43xx_phy_write(bcm, 0x04C0, 0xFFFF); - bcm43xx_phy_write(bcm, 0x04C1, 0x00A9); - } else { - bcm43xx_phy_write(bcm, 0x04C0, 0x00C1); - bcm43xx_phy_write(bcm, 0x04C1, 0x0059); - } - - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) - & 0xC0FF) | 0x1800); - bcm43xx_phy_write(bcm, 0x04A1, - (bcm43xx_phy_read(bcm, 0x04A1) - & 0xFFC0) | 0x0015); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) - & 0xCFFF) | 0x1000); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) - & 0xF0FF) | 0x0A00); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) - & 0xCFFF) | 0x1000); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) - & 0xF0FF) | 0x0800); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) - & 0xFFCF) | 0x0010); - bcm43xx_phy_write(bcm, 0x04AB, - (bcm43xx_phy_read(bcm, 0x04AB) - & 0xFFF0) | 0x0005); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) - & 0xFFCF) | 0x0010); - bcm43xx_phy_write(bcm, 0x04A8, - (bcm43xx_phy_read(bcm, 0x04A8) - & 0xFFF0) | 0x0006); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) - & 0xF0FF) | 0x0800); - bcm43xx_phy_write(bcm, 0x04A0, - (bcm43xx_phy_read(bcm, 0x04A0) - & 0xF0FF) | 0x0500); - bcm43xx_phy_write(bcm, 0x04A2, - (bcm43xx_phy_read(bcm, 0x04A2) - & 0xFFF0) | 0x000B); - - if (phy->rev >= 3) { - bcm43xx_phy_write(bcm, 0x048A, - bcm43xx_phy_read(bcm, 0x048A) - & ~0x8000); - bcm43xx_phy_write(bcm, 0x0415, - (bcm43xx_phy_read(bcm, 0x0415) - & 0x8000) | 0x36D8); - bcm43xx_phy_write(bcm, 0x0416, - (bcm43xx_phy_read(bcm, 0x0416) - & 0x8000) | 0x36D8); - bcm43xx_phy_write(bcm, 0x0417, - (bcm43xx_phy_read(bcm, 0x0417) - & 0xFE00) | 0x016D); - } else { - bcm43xx_phy_write(bcm, 0x048A, - bcm43xx_phy_read(bcm, 0x048A) - | 0x1000); - bcm43xx_phy_write(bcm, 0x048A, - (bcm43xx_phy_read(bcm, 0x048A) - & 0x9FFF) | 0x2000); - tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET); - if (!(tmp32 & 0x800)) { - tmp32 |= 0x800; - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - tmp32); - } - } - if (phy->rev >= 2) { - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) - | 0x0800); - } - bcm43xx_phy_write(bcm, 0x048C, - (bcm43xx_phy_read(bcm, 0x048C) - & 0xF0FF) | 0x0200); - if (phy->rev == 2) { - bcm43xx_phy_write(bcm, 0x04AE, - (bcm43xx_phy_read(bcm, 0x04AE) - & 0xFF00) | 0x007F); - bcm43xx_phy_write(bcm, 0x04AD, - (bcm43xx_phy_read(bcm, 0x04AD) - & 0x00FF) | 0x1300); - } else if (phy->rev >= 6) { - bcm43xx_ilt_write(bcm, 0x1A00 + 0x3, 0x007F); - bcm43xx_ilt_write(bcm, 0x1A00 + 0x2, 0x007F); - bcm43xx_phy_write(bcm, 0x04AD, - bcm43xx_phy_read(bcm, 0x04AD) - & 0x00FF); - } - bcm43xx_calc_nrssi_slope(bcm); - break; - default: - assert(0); - } -} - -static void -bcm43xx_radio_interference_mitigation_disable(struct bcm43xx_private *bcm, - int mode) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u32 tmp32; - u32 *stack = radio->interfstack; - - switch (mode) { - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - if (phy->rev != 1) { - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000); - break; - } - phy_stackrestore(0x0078); - bcm43xx_calc_nrssi_threshold(bcm); - phy_stackrestore(0x0406); - bcm43xx_phy_write(bcm, 0x042B, - bcm43xx_phy_read(bcm, 0x042B) & ~0x0800); - if (!bcm->bad_frames_preempt) { - bcm43xx_phy_write(bcm, BCM43xx_PHY_RADIO_BITFIELD, - bcm43xx_phy_read(bcm, BCM43xx_PHY_RADIO_BITFIELD) - & ~(1 << 11)); - } - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) | 0x4000); - phy_stackrestore(0x04A0); - phy_stackrestore(0x04A1); - phy_stackrestore(0x04A2); - phy_stackrestore(0x04A8); - phy_stackrestore(0x04AB); - phy_stackrestore(0x04A7); - phy_stackrestore(0x04A3); - phy_stackrestore(0x04A9); - phy_stackrestore(0x0493); - phy_stackrestore(0x04AA); - phy_stackrestore(0x04AC); - break; - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - if (!(bcm43xx_phy_read(bcm, 0x0033) & 0x0800)) - break; - - radio->aci_enable = 0; - - phy_stackrestore(BCM43xx_PHY_RADIO_BITFIELD); - phy_stackrestore(BCM43xx_PHY_G_CRS); - phy_stackrestore(0x0033); - phy_stackrestore(0x04A3); - phy_stackrestore(0x04A9); - phy_stackrestore(0x0493); - phy_stackrestore(0x04AA); - phy_stackrestore(0x04AC); - phy_stackrestore(0x04A0); - phy_stackrestore(0x04A7); - if (phy->rev >= 2) { - phy_stackrestore(0x04C0); - phy_stackrestore(0x04C1); - } else - phy_stackrestore(0x0406); - phy_stackrestore(0x04A1); - phy_stackrestore(0x04AB); - phy_stackrestore(0x04A8); - if (phy->rev == 2) { - phy_stackrestore(0x04AD); - phy_stackrestore(0x04AE); - } else if (phy->rev >= 3) { - phy_stackrestore(0x04AD); - phy_stackrestore(0x0415); - phy_stackrestore(0x0416); - phy_stackrestore(0x0417); - ilt_stackrestore(0x1A00 + 0x2); - ilt_stackrestore(0x1A00 + 0x3); - } - phy_stackrestore(0x04A2); - phy_stackrestore(0x04A8); - phy_stackrestore(0x042B); - phy_stackrestore(0x048C); - tmp32 = bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET); - if (tmp32 & 0x800) { - tmp32 &= ~0x800; - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - tmp32); - } - bcm43xx_calc_nrssi_slope(bcm); - break; - default: - assert(0); - } -} - -#undef phy_stacksave -#undef phy_stackrestore -#undef radio_stacksave -#undef radio_stackrestore -#undef ilt_stacksave -#undef ilt_stackrestore - -int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, - int mode) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int currentmode; - - if ((phy->type != BCM43xx_PHYTYPE_G) || - (phy->rev == 0) || - (!phy->connected)) - return -ENODEV; - - radio->aci_wlan_automatic = 0; - switch (mode) { - case BCM43xx_RADIO_INTERFMODE_AUTOWLAN: - radio->aci_wlan_automatic = 1; - if (radio->aci_enable) - mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; - else - mode = BCM43xx_RADIO_INTERFMODE_NONE; - break; - case BCM43xx_RADIO_INTERFMODE_NONE: - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - break; - default: - return -EINVAL; - } - - currentmode = radio->interfmode; - if (currentmode == mode) - return 0; - if (currentmode != BCM43xx_RADIO_INTERFMODE_NONE) - bcm43xx_radio_interference_mitigation_disable(bcm, currentmode); - - if (mode == BCM43xx_RADIO_INTERFMODE_NONE) { - radio->aci_enable = 0; - radio->aci_hw_rssi = 0; - } else - bcm43xx_radio_interference_mitigation_enable(bcm, mode); - radio->interfmode = mode; - - return 0; -} - -u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm) -{ - u16 reg, index, ret; - - reg = bcm43xx_radio_read16(bcm, 0x0060); - index = (reg & 0x001E) >> 1; - ret = rcc_table[index] << 1; - ret |= (reg & 0x0001); - ret |= 0x0020; - - return ret; -} - -#define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0)) -static u16 bcm43xx_get_812_value(struct bcm43xx_private *bcm, u8 lpd) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 loop_or = 0; - u16 adj_loopback_gain = phy->loopback_gain[0]; - u8 loop; - u16 extern_lna_control; - - if (!phy->connected) - return 0; - if (!has_loopback_gain(phy)) { - if (phy->rev < 7 || !(bcm->sprom.boardflags - & BCM43xx_BFL_EXTLNA)) { - switch (lpd) { - case LPD(0, 1, 1): - return 0x0FB2; - case LPD(0, 0, 1): - return 0x00B2; - case LPD(1, 0, 1): - return 0x30B2; - case LPD(1, 0, 0): - return 0x30B3; - default: - assert(0); - } - } else { - switch (lpd) { - case LPD(0, 1, 1): - return 0x8FB2; - case LPD(0, 0, 1): - return 0x80B2; - case LPD(1, 0, 1): - return 0x20B2; - case LPD(1, 0, 0): - return 0x20B3; - default: - assert(0); - } - } - } else { - if (radio->revision == 8) - adj_loopback_gain += 0x003E; - else - adj_loopback_gain += 0x0026; - if (adj_loopback_gain >= 0x46) { - adj_loopback_gain -= 0x46; - extern_lna_control = 0x3000; - } else if (adj_loopback_gain >= 0x3A) { - adj_loopback_gain -= 0x3A; - extern_lna_control = 0x2000; - } else if (adj_loopback_gain >= 0x2E) { - adj_loopback_gain -= 0x2E; - extern_lna_control = 0x1000; - } else { - adj_loopback_gain -= 0x10; - extern_lna_control = 0x0000; - } - for (loop = 0; loop < 16; loop++) { - u16 tmp = adj_loopback_gain - 6 * loop; - if (tmp < 6) - break; - } - - loop_or = (loop << 8) | extern_lna_control; - if (phy->rev >= 7 && bcm->sprom.boardflags - & BCM43xx_BFL_EXTLNA) { - if (extern_lna_control) - loop_or |= 0x8000; - switch (lpd) { - case LPD(0, 1, 1): - return 0x8F92; - case LPD(0, 0, 1): - return (0x8092 | loop_or); - case LPD(1, 0, 1): - return (0x2092 | loop_or); - case LPD(1, 0, 0): - return (0x2093 | loop_or); - default: - assert(0); - } - } else { - switch (lpd) { - case LPD(0, 1, 1): - return 0x0F92; - case LPD(0, 0, 1): - case LPD(1, 0, 1): - return (0x0092 | loop_or); - case LPD(1, 0, 0): - return (0x0093 | loop_or); - default: - assert(0); - } - } - } - return 0; -} - -u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 backup[21] = { 0 }; - u16 ret; - u16 i, j; - u32 tmp1 = 0, tmp2 = 0; - - backup[0] = bcm43xx_radio_read16(bcm, 0x0043); - backup[14] = bcm43xx_radio_read16(bcm, 0x0051); - backup[15] = bcm43xx_radio_read16(bcm, 0x0052); - backup[1] = bcm43xx_phy_read(bcm, 0x0015); - backup[16] = bcm43xx_phy_read(bcm, 0x005A); - backup[17] = bcm43xx_phy_read(bcm, 0x0059); - backup[18] = bcm43xx_phy_read(bcm, 0x0058); - if (phy->type == BCM43xx_PHYTYPE_B) { - backup[2] = bcm43xx_phy_read(bcm, 0x0030); - backup[3] = bcm43xx_read16(bcm, 0x03EC); - bcm43xx_phy_write(bcm, 0x0030, 0x00FF); - bcm43xx_write16(bcm, 0x03EC, 0x3F3F); - } else { - if (phy->connected) { - backup[4] = bcm43xx_phy_read(bcm, 0x0811); - backup[5] = bcm43xx_phy_read(bcm, 0x0812); - backup[6] = bcm43xx_phy_read(bcm, 0x0814); - backup[7] = bcm43xx_phy_read(bcm, 0x0815); - backup[8] = bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS); - backup[9] = bcm43xx_phy_read(bcm, 0x0802); - bcm43xx_phy_write(bcm, 0x0814, - (bcm43xx_phy_read(bcm, 0x0814) - | 0x0003)); - bcm43xx_phy_write(bcm, 0x0815, - (bcm43xx_phy_read(bcm, 0x0815) - & 0xFFFC)); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, - (bcm43xx_phy_read(bcm, BCM43xx_PHY_G_CRS) - & 0x7FFF)); - bcm43xx_phy_write(bcm, 0x0802, - (bcm43xx_phy_read(bcm, 0x0802) & 0xFFFC)); - if (phy->rev > 1) { /* loopback gain enabled */ - backup[19] = bcm43xx_phy_read(bcm, 0x080F); - backup[20] = bcm43xx_phy_read(bcm, 0x0810); - if (phy->rev >= 3) - bcm43xx_phy_write(bcm, 0x080F, 0xC020); - else - bcm43xx_phy_write(bcm, 0x080F, 0x8020); - bcm43xx_phy_write(bcm, 0x0810, 0x0000); - } - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(0, 1, 1))); - if (phy->rev < 7 || !(bcm->sprom.boardflags - & BCM43xx_BFL_EXTLNA)) - bcm43xx_phy_write(bcm, 0x0811, 0x01B3); - else - bcm43xx_phy_write(bcm, 0x0811, 0x09B3); - } - } - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, - (bcm43xx_read16(bcm, BCM43xx_MMIO_PHY_RADIO) | 0x8000)); - backup[10] = bcm43xx_phy_read(bcm, 0x0035); - bcm43xx_phy_write(bcm, 0x0035, - (bcm43xx_phy_read(bcm, 0x0035) & 0xFF7F)); - backup[11] = bcm43xx_read16(bcm, 0x03E6); - backup[12] = bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT); - - // Initialization - if (phy->analog == 0) { - bcm43xx_write16(bcm, 0x03E6, 0x0122); - } else { - if (phy->analog >= 2) - bcm43xx_phy_write(bcm, 0x0003, - (bcm43xx_phy_read(bcm, 0x0003) - & 0xFFBF) | 0x0040); - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - (bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) - | 0x2000)); - } - - ret = bcm43xx_radio_calibrationvalue(bcm); - - if (phy->type == BCM43xx_PHYTYPE_B) - bcm43xx_radio_write16(bcm, 0x0078, 0x0026); - - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(0, 1, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xBFAF); - bcm43xx_phy_write(bcm, 0x002B, 0x1403); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(0, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xBFA0); - bcm43xx_radio_write16(bcm, 0x0051, - (bcm43xx_radio_read16(bcm, 0x0051) | 0x0004)); - if (radio->revision == 8) - bcm43xx_radio_write16(bcm, 0x0043, 0x001F); - else { - bcm43xx_radio_write16(bcm, 0x0052, 0x0000); - bcm43xx_radio_write16(bcm, 0x0043, - (bcm43xx_radio_read16(bcm, 0x0043) & 0xFFF0) - | 0x0009); - } - bcm43xx_phy_write(bcm, 0x0058, 0x0000); - - for (i = 0; i < 16; i++) { - bcm43xx_phy_write(bcm, 0x005A, 0x0480); - bcm43xx_phy_write(bcm, 0x0059, 0xC810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); - udelay(10); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); - udelay(10); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(1, 0, 0))); - bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); - udelay(20); - tmp1 += bcm43xx_phy_read(bcm, 0x002D); - bcm43xx_phy_write(bcm, 0x0058, 0x0000); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); - } - - tmp1++; - tmp1 >>= 9; - udelay(10); - bcm43xx_phy_write(bcm, 0x0058, 0x0000); - - for (i = 0; i < 16; i++) { - bcm43xx_radio_write16(bcm, 0x0078, (flip_4bit(i) << 1) | 0x0020); - backup[13] = bcm43xx_radio_read16(bcm, 0x0078); - udelay(10); - for (j = 0; j < 16; j++) { - bcm43xx_phy_write(bcm, 0x005A, 0x0D80); - bcm43xx_phy_write(bcm, 0x0059, 0xC810); - bcm43xx_phy_write(bcm, 0x0058, 0x000D); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, - LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); - udelay(10); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, - LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xEFB0); - udelay(10); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, - LPD(1, 0, 0))); - bcm43xx_phy_write(bcm, 0x0015, 0xFFF0); - udelay(10); - tmp2 += bcm43xx_phy_read(bcm, 0x002D); - bcm43xx_phy_write(bcm, 0x0058, 0x0000); - if (phy->connected) - bcm43xx_phy_write(bcm, 0x0812, - bcm43xx_get_812_value(bcm, - LPD(1, 0, 1))); - bcm43xx_phy_write(bcm, 0x0015, 0xAFB0); - } - tmp2++; - tmp2 >>= 8; - if (tmp1 < tmp2) - break; - } - - /* Restore the registers */ - bcm43xx_phy_write(bcm, 0x0015, backup[1]); - bcm43xx_radio_write16(bcm, 0x0051, backup[14]); - bcm43xx_radio_write16(bcm, 0x0052, backup[15]); - bcm43xx_radio_write16(bcm, 0x0043, backup[0]); - bcm43xx_phy_write(bcm, 0x005A, backup[16]); - bcm43xx_phy_write(bcm, 0x0059, backup[17]); - bcm43xx_phy_write(bcm, 0x0058, backup[18]); - bcm43xx_write16(bcm, 0x03E6, backup[11]); - if (phy->analog != 0) - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, backup[12]); - bcm43xx_phy_write(bcm, 0x0035, backup[10]); - bcm43xx_radio_selectchannel(bcm, radio->channel, 1); - if (phy->type == BCM43xx_PHYTYPE_B) { - bcm43xx_phy_write(bcm, 0x0030, backup[2]); - bcm43xx_write16(bcm, 0x03EC, backup[3]); - } else { - if (phy->connected) { - bcm43xx_write16(bcm, BCM43xx_MMIO_PHY_RADIO, - (bcm43xx_read16(bcm, - BCM43xx_MMIO_PHY_RADIO) & 0x7FFF)); - bcm43xx_phy_write(bcm, 0x0811, backup[4]); - bcm43xx_phy_write(bcm, 0x0812, backup[5]); - bcm43xx_phy_write(bcm, 0x0814, backup[6]); - bcm43xx_phy_write(bcm, 0x0815, backup[7]); - bcm43xx_phy_write(bcm, BCM43xx_PHY_G_CRS, backup[8]); - bcm43xx_phy_write(bcm, 0x0802, backup[9]); - if (phy->rev > 1) { - bcm43xx_phy_write(bcm, 0x080F, backup[19]); - bcm43xx_phy_write(bcm, 0x0810, backup[20]); - } - } - } - if (i >= 15) - ret = backup[13]; - - return ret; -} - -void bcm43xx_radio_init2060(struct bcm43xx_private *bcm) -{ - int err; - - bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); - bcm43xx_radio_write16(bcm, 0x0005, 0x0008); - bcm43xx_radio_write16(bcm, 0x0009, 0x0040); - bcm43xx_radio_write16(bcm, 0x0005, 0x00AA); - bcm43xx_radio_write16(bcm, 0x0032, 0x008F); - bcm43xx_radio_write16(bcm, 0x0006, 0x008F); - bcm43xx_radio_write16(bcm, 0x0034, 0x008F); - bcm43xx_radio_write16(bcm, 0x002C, 0x0007); - bcm43xx_radio_write16(bcm, 0x0082, 0x0080); - bcm43xx_radio_write16(bcm, 0x0080, 0x0000); - bcm43xx_radio_write16(bcm, 0x003F, 0x00DA); - bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); - bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0010); - bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); - bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020); - udelay(400); - - bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0020) | 0x0010); - udelay(400); - - bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008) | 0x0008); - bcm43xx_radio_write16(bcm, 0x0085, bcm43xx_radio_read16(bcm, 0x0085) & ~0x0010); - bcm43xx_radio_write16(bcm, 0x0005, bcm43xx_radio_read16(bcm, 0x0005) & ~0x0008); - bcm43xx_radio_write16(bcm, 0x0081, bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040); - bcm43xx_radio_write16(bcm, 0x0081, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0040) | 0x0040); - bcm43xx_radio_write16(bcm, 0x0005, (bcm43xx_radio_read16(bcm, 0x0081) & ~0x0008) | 0x0008); - bcm43xx_phy_write(bcm, 0x0063, 0xDDC6); - bcm43xx_phy_write(bcm, 0x0069, 0x07BE); - bcm43xx_phy_write(bcm, 0x006A, 0x0000); - - err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_A, 0); - assert(err == 0); - udelay(1000); -} - -static inline -u16 freq_r3A_value(u16 frequency) -{ - u16 value; - - if (frequency < 5091) - value = 0x0040; - else if (frequency < 5321) - value = 0x0000; - else if (frequency < 5806) - value = 0x0080; - else - value = 0x0040; - - return value; -} - -void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm) -{ - static const u8 data_high[5] = { 0x00, 0x40, 0x80, 0x90, 0xD0 }; - static const u8 data_low[5] = { 0x00, 0x01, 0x05, 0x06, 0x0A }; - u16 tmp = bcm43xx_radio_read16(bcm, 0x001E); - int i, j; - - for (i = 0; i < 5; i++) { - for (j = 0; j < 5; j++) { - if (tmp == (data_high[i] | data_low[j])) { - bcm43xx_phy_write(bcm, 0x0069, (i - j) << 8 | 0x00C0); - return; - } - } - } -} - -int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, - u8 channel, - int synthetic_pu_workaround) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 r8, tmp; - u16 freq; - - if (!ieee80211_is_valid_channel(bcm->ieee, channel)) - return -EINVAL; - if ((radio->manufact == 0x17F) && - (radio->version == 0x2060) && - (radio->revision == 1)) { - freq = channel2freq_a(channel); - - r8 = bcm43xx_radio_read16(bcm, 0x0008); - bcm43xx_write16(bcm, 0x03F0, freq); - bcm43xx_radio_write16(bcm, 0x0008, r8); - - TODO();//TODO: write max channel TX power? to Radio 0x2D - tmp = bcm43xx_radio_read16(bcm, 0x002E); - tmp &= 0x0080; - TODO();//TODO: OR tmp with the Power out estimation for this channel? - bcm43xx_radio_write16(bcm, 0x002E, tmp); - - if (freq >= 4920 && freq <= 5500) { - /* - * r8 = (((freq * 15 * 0xE1FC780F) >> 32) / 29) & 0x0F; - * = (freq * 0.025862069 - */ - r8 = 3 * freq / 116; /* is equal to r8 = freq * 0.025862 */ - } - bcm43xx_radio_write16(bcm, 0x0007, (r8 << 4) | r8); - bcm43xx_radio_write16(bcm, 0x0020, (r8 << 4) | r8); - bcm43xx_radio_write16(bcm, 0x0021, (r8 << 4) | r8); - bcm43xx_radio_write16(bcm, 0x0022, - (bcm43xx_radio_read16(bcm, 0x0022) - & 0x000F) | (r8 << 4)); - bcm43xx_radio_write16(bcm, 0x002A, (r8 << 4)); - bcm43xx_radio_write16(bcm, 0x002B, (r8 << 4)); - bcm43xx_radio_write16(bcm, 0x0008, - (bcm43xx_radio_read16(bcm, 0x0008) - & 0x00F0) | (r8 << 4)); - bcm43xx_radio_write16(bcm, 0x0029, - (bcm43xx_radio_read16(bcm, 0x0029) - & 0xFF0F) | 0x00B0); - bcm43xx_radio_write16(bcm, 0x0035, 0x00AA); - bcm43xx_radio_write16(bcm, 0x0036, 0x0085); - bcm43xx_radio_write16(bcm, 0x003A, - (bcm43xx_radio_read16(bcm, 0x003A) - & 0xFF20) | freq_r3A_value(freq)); - bcm43xx_radio_write16(bcm, 0x003D, - bcm43xx_radio_read16(bcm, 0x003D) & 0x00FF); - bcm43xx_radio_write16(bcm, 0x0081, - (bcm43xx_radio_read16(bcm, 0x0081) - & 0xFF7F) | 0x0080); - bcm43xx_radio_write16(bcm, 0x0035, - bcm43xx_radio_read16(bcm, 0x0035) & 0xFFEF); - bcm43xx_radio_write16(bcm, 0x0035, - (bcm43xx_radio_read16(bcm, 0x0035) - & 0xFFEF) | 0x0010); - bcm43xx_radio_set_tx_iq(bcm); - TODO(); //TODO: TSSI2dbm workaround - bcm43xx_phy_xmitpower(bcm);//FIXME correct? - } else { - if (synthetic_pu_workaround) - bcm43xx_synth_pu_workaround(bcm, channel); - - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL, - channel2freq_bg(channel)); - - if (channel == 14) { - if (bcm->sprom.locale == BCM43xx_LOCALE_JAPAN) { - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET) - & ~(1 << 7)); - } else { - bcm43xx_shm_write32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET, - bcm43xx_shm_read32(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODEFLAGS_OFFSET) - | (1 << 7)); - } - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) - | (1 << 11)); - } else { - bcm43xx_write16(bcm, BCM43xx_MMIO_CHANNEL_EXT, - bcm43xx_read16(bcm, BCM43xx_MMIO_CHANNEL_EXT) - & 0xF7BF); - } - } - - radio->channel = channel; - //XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states - // that 2000 usecs might suffice. - udelay(8000); - - return 0; -} - -void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val) -{ - u16 tmp; - - val <<= 8; - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0022) & 0xFCFF; - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0022, tmp | val); - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x03A8) & 0xFCFF; - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x03A8, tmp | val); - tmp = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, 0x0054) & 0xFCFF; - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0054, tmp | val); -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */ -static u16 bcm43xx_get_txgain_base_band(u16 txpower) -{ - u16 ret; - - assert(txpower <= 63); - - if (txpower >= 54) - ret = 2; - else if (txpower >= 49) - ret = 4; - else if (txpower >= 44) - ret = 5; - else - ret = 6; - - return ret; -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */ -static u16 bcm43xx_get_txgain_freq_power_amp(u16 txpower) -{ - u16 ret; - - assert(txpower <= 63); - - if (txpower >= 32) - ret = 0; - else if (txpower >= 25) - ret = 1; - else if (txpower >= 20) - ret = 2; - else if (txpower >= 12) - ret = 3; - else - ret = 4; - - return ret; -} - -/* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */ -static u16 bcm43xx_get_txgain_dac(u16 txpower) -{ - u16 ret; - - assert(txpower <= 63); - - if (txpower >= 54) - ret = txpower - 53; - else if (txpower >= 49) - ret = txpower - 42; - else if (txpower >= 44) - ret = txpower - 37; - else if (txpower >= 32) - ret = txpower - 32; - else if (txpower >= 25) - ret = txpower - 20; - else if (txpower >= 20) - ret = txpower - 13; - else if (txpower >= 12) - ret = txpower - 8; - else - ret = txpower; - - return ret; -} - -void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 pamp, base, dac, ilt; - - txpower = limit_value(txpower, 0, 63); - - pamp = bcm43xx_get_txgain_freq_power_amp(txpower); - pamp <<= 5; - pamp &= 0x00E0; - bcm43xx_phy_write(bcm, 0x0019, pamp); - - base = bcm43xx_get_txgain_base_band(txpower); - base &= 0x000F; - bcm43xx_phy_write(bcm, 0x0017, base | 0x0020); - - ilt = bcm43xx_ilt_read(bcm, 0x3001); - ilt &= 0x0007; - - dac = bcm43xx_get_txgain_dac(txpower); - dac <<= 3; - dac |= ilt; - - bcm43xx_ilt_write(bcm, 0x3001, dac); - - radio->txpwr_offset = txpower; - - TODO(); - //TODO: FuncPlaceholder (Adjust BB loft cancel) -} - -void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, - u16 baseband_attenuation, u16 radio_attenuation, - u16 txpower) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - if (baseband_attenuation == 0xFFFF) - baseband_attenuation = radio->baseband_atten; - if (radio_attenuation == 0xFFFF) - radio_attenuation = radio->radio_atten; - if (txpower == 0xFFFF) - txpower = radio->txctl1; - radio->baseband_atten = baseband_attenuation; - radio->radio_atten = radio_attenuation; - radio->txctl1 = txpower; - - assert(/*baseband_attenuation >= 0 &&*/ baseband_attenuation <= 11); - if (radio->revision < 6) - assert(/*radio_attenuation >= 0 &&*/ radio_attenuation <= 9); - else - assert(/* radio_attenuation >= 0 &&*/ radio_attenuation <= 31); - assert(/*txpower >= 0 &&*/ txpower <= 7); - - bcm43xx_phy_set_baseband_attenuation(bcm, baseband_attenuation); - bcm43xx_radio_write16(bcm, 0x0043, radio_attenuation); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0064, radio_attenuation); - if (radio->version == 0x2050) { - bcm43xx_radio_write16(bcm, 0x0052, - (bcm43xx_radio_read16(bcm, 0x0052) & ~0x0070) - | ((txpower << 4) & 0x0070)); - } - //FIXME: The spec is very weird and unclear here. - if (phy->type == BCM43xx_PHYTYPE_G) - bcm43xx_phy_lo_adjust(bcm, 0); -} - -u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - if (radio->version == 0x2050 && radio->revision < 6) - return 0; - return 2; -} - -u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - u16 att = 0xFFFF; - - if (phy->type == BCM43xx_PHYTYPE_A) - return 0x60; - - switch (radio->version) { - case 0x2053: - switch (radio->revision) { - case 1: - att = 6; - break; - } - break; - case 0x2050: - switch (radio->revision) { - case 0: - att = 5; - break; - case 1: - if (phy->type == BCM43xx_PHYTYPE_G) { - if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x421 && - bcm->board_revision >= 30) - att = 3; - else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x416) - att = 3; - else - att = 1; - } else { - if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x421 && - bcm->board_revision >= 30) - att = 7; - else - att = 6; - } - break; - case 2: - if (phy->type == BCM43xx_PHYTYPE_G) { - if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x421 && - bcm->board_revision >= 30) - att = 3; - else if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x416) - att = 5; - else if (bcm->chip_id == 0x4320) - att = 4; - else - att = 3; - } else - att = 6; - break; - case 3: - att = 5; - break; - case 4: - case 5: - att = 1; - break; - case 6: - case 7: - att = 5; - break; - case 8: - att = 0x1A; - break; - case 9: - default: - att = 5; - } - } - if (bcm->board_vendor == PCI_VENDOR_ID_BROADCOM && - bcm->board_type == 0x421) { - if (bcm->board_revision < 0x43) - att = 2; - else if (bcm->board_revision < 0x51) - att = 3; - } - if (att == 0xFFFF) - att = 5; - - return att; -} - -u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - if (radio->version != 0x2050) - return 0; - if (radio->revision == 1) - return 3; - if (radio->revision < 6) - return 2; - if (radio->revision == 8) - return 1; - return 0; -} - -void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - int err; - - if (radio->enabled) - return; - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - bcm43xx_radio_write16(bcm, 0x0004, 0x00C0); - bcm43xx_radio_write16(bcm, 0x0005, 0x0008); - bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) & 0xFFF7); - bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) & 0xFFF7); - bcm43xx_radio_init2060(bcm); - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - bcm43xx_phy_write(bcm, 0x0015, 0x8000); - bcm43xx_phy_write(bcm, 0x0015, 0xCC00); - bcm43xx_phy_write(bcm, 0x0015, (phy->connected ? 0x00C0 : 0x0000)); - err = bcm43xx_radio_selectchannel(bcm, BCM43xx_RADIO_DEFAULT_CHANNEL_BG, 1); - assert(err == 0); - break; - default: - assert(0); - } - radio->enabled = 1; - dprintk(KERN_INFO PFX "Radio turned on\n"); - bcm43xx_leds_update(bcm, 0); -} - -void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - - if (phy->type == BCM43xx_PHYTYPE_A) { - bcm43xx_radio_write16(bcm, 0x0004, 0x00FF); - bcm43xx_radio_write16(bcm, 0x0005, 0x00FB); - bcm43xx_phy_write(bcm, 0x0010, bcm43xx_phy_read(bcm, 0x0010) | 0x0008); - bcm43xx_phy_write(bcm, 0x0011, bcm43xx_phy_read(bcm, 0x0011) | 0x0008); - } - if (phy->type == BCM43xx_PHYTYPE_G && bcm->current_core->rev >= 5) { - bcm43xx_phy_write(bcm, 0x0811, bcm43xx_phy_read(bcm, 0x0811) | 0x008C); - bcm43xx_phy_write(bcm, 0x0812, bcm43xx_phy_read(bcm, 0x0812) & 0xFF73); - } else - bcm43xx_phy_write(bcm, 0x0015, 0xAA00); - radio->enabled = 0; - dprintk(KERN_INFO PFX "Radio initialized\n"); - bcm43xx_leds_update(bcm, 0); -} - -void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0068, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x006a, 0x7F7F); - break; - case BCM43xx_PHYTYPE_B: - case BCM43xx_PHYTYPE_G: - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0058, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x005a, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0070, 0x7F7F); - bcm43xx_shm_write16(bcm, BCM43xx_SHM_SHARED, 0x0072, 0x7F7F); - break; - } -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h b/drivers/net/wireless/bcm43xx/bcm43xx_radio.h deleted file mode 100644 index 77a98a53a2e2..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_radio.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_RADIO_H_ -#define BCM43xx_RADIO_H_ - -#include "bcm43xx.h" - - -#define BCM43xx_RADIO_DEFAULT_CHANNEL_A 36 -#define BCM43xx_RADIO_DEFAULT_CHANNEL_BG 6 - -/* Force antenna 0. */ -#define BCM43xx_RADIO_TXANTENNA_0 0 -/* Force antenna 1. */ -#define BCM43xx_RADIO_TXANTENNA_1 1 -/* Use the RX antenna, that was selected for the most recently - * received good PLCP header. - */ -#define BCM43xx_RADIO_TXANTENNA_LASTPLCP 3 -#define BCM43xx_RADIO_TXANTENNA_DEFAULT BCM43xx_RADIO_TXANTENNA_LASTPLCP - -#define BCM43xx_RADIO_INTERFMODE_NONE 0 -#define BCM43xx_RADIO_INTERFMODE_NONWLAN 1 -#define BCM43xx_RADIO_INTERFMODE_MANUALWLAN 2 -#define BCM43xx_RADIO_INTERFMODE_AUTOWLAN 3 - - -void bcm43xx_radio_lock(struct bcm43xx_private *bcm); -void bcm43xx_radio_unlock(struct bcm43xx_private *bcm); - -u16 bcm43xx_radio_read16(struct bcm43xx_private *bcm, u16 offset); -void bcm43xx_radio_write16(struct bcm43xx_private *bcm, u16 offset, u16 val); - -u16 bcm43xx_radio_init2050(struct bcm43xx_private *bcm); -void bcm43xx_radio_init2060(struct bcm43xx_private *bcm); - -void bcm43xx_radio_turn_on(struct bcm43xx_private *bcm); -void bcm43xx_radio_turn_off(struct bcm43xx_private *bcm); - -static inline -int bcm43xx_is_hw_radio_enabled(struct bcm43xx_private *bcm) -{ - /* function to return state of hardware enable of radio - * returns 0 if radio disabled, 1 if radio enabled - */ - if (bcm->current_core->rev >= 3) - return ((bcm43xx_read32(bcm, BCM43xx_MMIO_RADIO_HWENABLED_HI) - & BCM43xx_MMIO_RADIO_HWENABLED_HI_MASK) - == 0) ? 1 : 0; - else - return ((bcm43xx_read16(bcm, BCM43xx_MMIO_RADIO_HWENABLED_LO) - & BCM43xx_MMIO_RADIO_HWENABLED_LO_MASK) - == 0) ? 0 : 1; -} - -int bcm43xx_radio_selectchannel(struct bcm43xx_private *bcm, u8 channel, - int synthetic_pu_workaround); - -void bcm43xx_radio_set_txpower_a(struct bcm43xx_private *bcm, u16 txpower); -void bcm43xx_radio_set_txpower_bg(struct bcm43xx_private *bcm, - u16 baseband_attenuation, u16 attenuation, - u16 txpower); - -u16 bcm43xx_default_baseband_attenuation(struct bcm43xx_private *bcm); -u16 bcm43xx_default_radio_attenuation(struct bcm43xx_private *bcm); -u16 bcm43xx_default_txctl1(struct bcm43xx_private *bcm); - -void bcm43xx_radio_set_txantenna(struct bcm43xx_private *bcm, u32 val); - -void bcm43xx_radio_clear_tssi(struct bcm43xx_private *bcm); - -u8 bcm43xx_radio_aci_detect(struct bcm43xx_private *bcm, u8 channel); -u8 bcm43xx_radio_aci_scan(struct bcm43xx_private *bcm); - -int bcm43xx_radio_set_interference_mitigation(struct bcm43xx_private *bcm, int mode); - -void bcm43xx_calc_nrssi_slope(struct bcm43xx_private *bcm); -void bcm43xx_calc_nrssi_threshold(struct bcm43xx_private *bcm); -s16 bcm43xx_nrssi_hw_read(struct bcm43xx_private *bcm, u16 offset); -void bcm43xx_nrssi_hw_write(struct bcm43xx_private *bcm, u16 offset, s16 val); -void bcm43xx_nrssi_hw_update(struct bcm43xx_private *bcm, u16 val); -void bcm43xx_nrssi_mem_update(struct bcm43xx_private *bcm); - -void bcm43xx_radio_set_tx_iq(struct bcm43xx_private *bcm); -u16 bcm43xx_radio_calibrationvalue(struct bcm43xx_private *bcm); - -#endif /* BCM43xx_RADIO_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c deleted file mode 100644 index 8ab5f93d192a..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.c +++ /dev/null @@ -1,471 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - SYSFS support routines - - Copyright (c) 2006 Michael Buesch - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx_sysfs.h" -#include "bcm43xx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_radio.h" - -#include - - -#define GENERIC_FILESIZE 64 - - -static int get_integer(const char *buf, size_t count) -{ - char tmp[10 + 1] = { 0 }; - int ret = -EINVAL; - - if (count == 0) - goto out; - count = min(count, (size_t)10); - memcpy(tmp, buf, count); - ret = simple_strtol(tmp, NULL, 10); -out: - return ret; -} - -static int get_boolean(const char *buf, size_t count) -{ - if (count != 0) { - if (buf[0] == '1') - return 1; - if (buf[0] == '0') - return 0; - if (count >= 4 && memcmp(buf, "true", 4) == 0) - return 1; - if (count >= 5 && memcmp(buf, "false", 5) == 0) - return 0; - if (count >= 3 && memcmp(buf, "yes", 3) == 0) - return 1; - if (count >= 2 && memcmp(buf, "no", 2) == 0) - return 0; - if (count >= 2 && memcmp(buf, "on", 2) == 0) - return 1; - if (count >= 3 && memcmp(buf, "off", 3) == 0) - return 0; - } - return -EINVAL; -} - -static int sprom2hex(const u16 *sprom, char *buf, size_t buf_len) -{ - int i, pos = 0; - - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { - pos += snprintf(buf + pos, buf_len - pos - 1, - "%04X", swab16(sprom[i]) & 0xFFFF); - } - pos += snprintf(buf + pos, buf_len - pos - 1, "\n"); - - return pos + 1; -} - -static int hex2sprom(u16 *sprom, const char *dump, size_t len) -{ - char tmp[5] = { 0 }; - int cnt = 0; - unsigned long parsed; - - if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) - return -EINVAL; - - while (cnt < BCM43xx_SPROM_SIZE) { - memcpy(tmp, dump, 4); - dump += 4; - parsed = simple_strtoul(tmp, NULL, 16); - sprom[cnt++] = swab16((u16)parsed); - } - - return 0; -} - -static ssize_t bcm43xx_attr_sprom_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - u16 *sprom; - unsigned long flags; - int err; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - assert(BCM43xx_SPROM_SIZE * sizeof(u16) <= PAGE_SIZE); - sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), - GFP_KERNEL); - if (!sprom) - return -ENOMEM; - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - err = bcm43xx_sprom_read(bcm, sprom); - if (!err) - err = sprom2hex(sprom, buf, PAGE_SIZE); - mmiowb(); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - kfree(sprom); - - return err; -} - -static ssize_t bcm43xx_attr_sprom_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - u16 *sprom; - unsigned long flags; - int err; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), - GFP_KERNEL); - if (!sprom) - return -ENOMEM; - err = hex2sprom(sprom, buf, count); - if (err) - goto out_kfree; - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - spin_lock(&bcm->leds_lock); - err = bcm43xx_sprom_write(bcm, sprom); - mmiowb(); - spin_unlock(&bcm->leds_lock); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -out_kfree: - kfree(sprom); - - return err ? err : count; - -} - -static DEVICE_ATTR(sprom, 0600, - bcm43xx_attr_sprom_show, - bcm43xx_attr_sprom_store); - -static ssize_t bcm43xx_attr_interfmode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - ssize_t count = 0; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&bcm->mutex); - - switch (bcm43xx_current_radio(bcm)->interfmode) { - case BCM43xx_RADIO_INTERFMODE_NONE: - count = snprintf(buf, PAGE_SIZE, "0 (No Interference Mitigation)\n"); - break; - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - count = snprintf(buf, PAGE_SIZE, "1 (Non-WLAN Interference Mitigation)\n"); - break; - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - count = snprintf(buf, PAGE_SIZE, "2 (WLAN Interference Mitigation)\n"); - break; - default: - assert(0); - } - - mutex_unlock(&bcm->mutex); - - return count; - -} - -static ssize_t bcm43xx_attr_interfmode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - unsigned long flags; - int err; - int mode; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mode = get_integer(buf, count); - switch (mode) { - case 0: - mode = BCM43xx_RADIO_INTERFMODE_NONE; - break; - case 1: - mode = BCM43xx_RADIO_INTERFMODE_NONWLAN; - break; - case 2: - mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; - break; - case 3: - mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; - break; - default: - return -EINVAL; - } - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - err = bcm43xx_radio_set_interference_mitigation(bcm, mode); - if (err) { - printk(KERN_ERR PFX "Interference Mitigation not " - "supported by device\n"); - } - mmiowb(); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err ? err : count; -} - -static DEVICE_ATTR(interference, 0644, - bcm43xx_attr_interfmode_show, - bcm43xx_attr_interfmode_store); - -static ssize_t bcm43xx_attr_preamble_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - ssize_t count; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&bcm->mutex); - - if (bcm->short_preamble) - count = snprintf(buf, PAGE_SIZE, "1 (Short Preamble enabled)\n"); - else - count = snprintf(buf, PAGE_SIZE, "0 (Short Preamble disabled)\n"); - - mutex_unlock(&bcm->mutex); - - return count; -} - -static ssize_t bcm43xx_attr_preamble_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - unsigned long flags; - int value; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - value = get_boolean(buf, count); - if (value < 0) - return value; - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - bcm->short_preamble = !!value; - - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return count; -} - -static DEVICE_ATTR(shortpreamble, 0644, - bcm43xx_attr_preamble_show, - bcm43xx_attr_preamble_store); - -static ssize_t bcm43xx_attr_phymode_store(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - int phytype; - int err = -EINVAL; - - if (count < 1) - goto out; - switch (buf[0]) { - case 'a': case 'A': - phytype = BCM43xx_PHYTYPE_A; - break; - case 'b': case 'B': - phytype = BCM43xx_PHYTYPE_B; - break; - case 'g': case 'G': - phytype = BCM43xx_PHYTYPE_G; - break; - default: - goto out; - } - - bcm43xx_cancel_work(bcm); - mutex_lock(&(bcm)->mutex); - err = bcm43xx_select_wireless_core(bcm, phytype); - if (!err) - bcm43xx_periodic_tasks_setup(bcm); - mutex_unlock(&(bcm)->mutex); - if (err == -ESRCH) - err = -ENODEV; - -out: - return err ? err : count; -} - -static ssize_t bcm43xx_attr_phymode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct bcm43xx_private *bcm = dev_to_bcm(dev); - ssize_t count = 0; - - mutex_lock(&(bcm)->mutex); - switch (bcm43xx_current_phy(bcm)->type) { - case BCM43xx_PHYTYPE_A: - snprintf(buf, PAGE_SIZE, "A"); - break; - case BCM43xx_PHYTYPE_B: - snprintf(buf, PAGE_SIZE, "B"); - break; - case BCM43xx_PHYTYPE_G: - snprintf(buf, PAGE_SIZE, "G"); - break; - default: - assert(0); - } - mutex_unlock(&(bcm)->mutex); - - return count; -} - -static DEVICE_ATTR(phymode, 0644, - bcm43xx_attr_phymode_show, - bcm43xx_attr_phymode_store); - -static ssize_t bcm43xx_attr_microcode_show(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - unsigned long flags; - struct bcm43xx_private *bcm = dev_to_bcm(dev); - ssize_t count = 0; - u16 status; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - mutex_lock(&(bcm)->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - status = bcm43xx_shm_read16(bcm, BCM43xx_SHM_SHARED, - BCM43xx_UCODE_STATUS); - - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&(bcm)->mutex); - switch (status) { - case 0x0000: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (invalid)\n", - status); - break; - case 0x0001: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (init)\n", - status); - break; - case 0x0002: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (active)\n", - status); - break; - case 0x0003: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (suspended)\n", - status); - break; - case 0x0004: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (asleep)\n", - status); - break; - default: - count = snprintf(buf, PAGE_SIZE, "0x%.4x (unknown)\n", - status); - break; - } - - return count; -} - -static DEVICE_ATTR(microcodestatus, 0444, - bcm43xx_attr_microcode_show, - NULL); - -int bcm43xx_sysfs_register(struct bcm43xx_private *bcm) -{ - struct device *dev = &bcm->pci_dev->dev; - int err; - - assert(bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED); - - err = device_create_file(dev, &dev_attr_sprom); - if (err) - goto out; - err = device_create_file(dev, &dev_attr_interference); - if (err) - goto err_remove_sprom; - err = device_create_file(dev, &dev_attr_shortpreamble); - if (err) - goto err_remove_interfmode; - err = device_create_file(dev, &dev_attr_phymode); - if (err) - goto err_remove_shortpreamble; - err = device_create_file(dev, &dev_attr_microcodestatus); - if (err) - goto err_remove_phymode; - -out: - return err; -err_remove_phymode: - device_remove_file(dev, &dev_attr_phymode); -err_remove_shortpreamble: - device_remove_file(dev, &dev_attr_shortpreamble); -err_remove_interfmode: - device_remove_file(dev, &dev_attr_interference); -err_remove_sprom: - device_remove_file(dev, &dev_attr_sprom); - goto out; -} - -void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm) -{ - struct device *dev = &bcm->pci_dev->dev; - - device_remove_file(dev, &dev_attr_microcodestatus); - device_remove_file(dev, &dev_attr_phymode); - device_remove_file(dev, &dev_attr_shortpreamble); - device_remove_file(dev, &dev_attr_interference); - device_remove_file(dev, &dev_attr_sprom); -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h b/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h deleted file mode 100644 index cc701df71e2a..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_sysfs.h +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef BCM43xx_SYSFS_H_ -#define BCM43xx_SYSFS_H_ - -struct bcm43xx_private; - -int bcm43xx_sysfs_register(struct bcm43xx_private *bcm); -void bcm43xx_sysfs_unregister(struct bcm43xx_private *bcm); - -#endif /* BCM43xx_SYSFS_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c b/drivers/net/wireless/bcm43xx/bcm43xx_wx.c deleted file mode 100644 index 6acfdc49dccd..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.c +++ /dev/null @@ -1,1035 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include -#include -#include -#include -#include -#include - -#include "bcm43xx.h" -#include "bcm43xx_wx.h" -#include "bcm43xx_main.h" -#include "bcm43xx_radio.h" -#include "bcm43xx_phy.h" - - -/* The WIRELESS_EXT version, which is implemented by this driver. */ -#define BCM43xx_WX_VERSION 18 - -#define MAX_WX_STRING 80 - -static int bcm43xx_wx_get_name(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int i; - struct bcm43xx_phyinfo *phy; - char suffix[7] = { 0 }; - int have_a = 0, have_b = 0, have_g = 0; - - mutex_lock(&bcm->mutex); - for (i = 0; i < bcm->nr_80211_available; i++) { - phy = &(bcm->core_80211_ext[i].phy); - switch (phy->type) { - case BCM43xx_PHYTYPE_A: - have_a = 1; - break; - case BCM43xx_PHYTYPE_G: - have_g = 1; - case BCM43xx_PHYTYPE_B: - have_b = 1; - break; - default: - assert(0); - } - } - mutex_unlock(&bcm->mutex); - - i = 0; - if (have_a) { - suffix[i++] = 'a'; - suffix[i++] = '/'; - } - if (have_b) { - suffix[i++] = 'b'; - suffix[i++] = '/'; - } - if (have_g) { - suffix[i++] = 'g'; - suffix[i++] = '/'; - } - if (i != 0) - suffix[i - 1] = '\0'; - - snprintf(data->name, IFNAMSIZ, "IEEE 802.11%s", suffix); - - return 0; -} - -static int bcm43xx_wx_set_channelfreq(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - u8 channel; - s8 expon; - int freq; - int err = -EINVAL; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - - if ((data->freq.e == 0) && - (data->freq.m >= 0) && (data->freq.m <= 1000)) { - channel = data->freq.m; - freq = bcm43xx_channel_to_freq(bcm, channel); - } else { - freq = data->freq.m; - expon = 6 - data->freq.e; - while (--expon >= 0) /* scale down the frequency to MHz */ - freq /= 10; - assert(freq > 1000); - channel = bcm43xx_freq_to_channel(bcm, freq); - } - if (!ieee80211_is_valid_channel(bcm->ieee, channel)) - goto out_unlock; - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - //ieee80211softmac_disassoc(softmac, $REASON); - bcm43xx_mac_suspend(bcm); - err = bcm43xx_radio_selectchannel(bcm, channel, 0); - bcm43xx_mac_enable(bcm); - } else { - bcm43xx_current_radio(bcm)->initial_channel = channel; - err = 0; - } -out_unlock: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_channelfreq(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct bcm43xx_radioinfo *radio; - int err = -ENODEV; - u16 channel; - - mutex_lock(&bcm->mutex); - radio = bcm43xx_current_radio(bcm); - channel = radio->channel; - if (channel == 0xFF) { - channel = radio->initial_channel; - if (channel == 0xFF) - goto out_unlock; - } - assert(channel > 0 && channel <= 1000); - data->freq.e = 1; - data->freq.m = bcm43xx_channel_to_freq(bcm, channel) * 100000; - data->freq.flags = 1; - - err = 0; -out_unlock: - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_set_mode(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int mode; - - mode = data->mode; - if (mode == IW_MODE_AUTO) - mode = BCM43xx_INITIAL_IWMODE; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - if (bcm->ieee->iw_mode != mode) - bcm43xx_set_iwmode(bcm, mode); - } else - bcm->ieee->iw_mode = mode; - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_mode(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - mutex_lock(&bcm->mutex); - data->mode = bcm->ieee->iw_mode; - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_rangeparams(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct iw_range *range = (struct iw_range *)extra; - const struct ieee80211_geo *geo; - int i, j; - struct bcm43xx_phyinfo *phy; - - data->data.length = sizeof(*range); - memset(range, 0, sizeof(*range)); - - //TODO: What about 802.11b? - /* 54Mb/s == ~27Mb/s payload throughput (802.11g) */ - range->throughput = 27 * 1000 * 1000; - - range->max_qual.qual = 100; - range->max_qual.level = 146; /* set floor at -110 dBm (146 - 256) */ - range->max_qual.noise = 146; - range->max_qual.updated = IW_QUAL_ALL_UPDATED; - - range->avg_qual.qual = 50; - range->avg_qual.level = 0; - range->avg_qual.noise = 0; - range->avg_qual.updated = IW_QUAL_ALL_UPDATED; - - range->min_rts = BCM43xx_MIN_RTS_THRESHOLD; - range->max_rts = BCM43xx_MAX_RTS_THRESHOLD; - range->min_frag = MIN_FRAG_THRESHOLD; - range->max_frag = MAX_FRAG_THRESHOLD; - - range->encoding_size[0] = 5; - range->encoding_size[1] = 13; - range->num_encoding_sizes = 2; - range->max_encoding_tokens = WEP_KEYS; - - range->we_version_compiled = WIRELESS_EXT; - range->we_version_source = BCM43xx_WX_VERSION; - - range->enc_capa = IW_ENC_CAPA_WPA | - IW_ENC_CAPA_WPA2 | - IW_ENC_CAPA_CIPHER_TKIP | - IW_ENC_CAPA_CIPHER_CCMP; - - mutex_lock(&bcm->mutex); - phy = bcm43xx_current_phy(bcm); - - range->num_bitrates = 0; - i = 0; - if (phy->type == BCM43xx_PHYTYPE_A || - phy->type == BCM43xx_PHYTYPE_G) { - range->num_bitrates = 8; - range->bitrate[i++] = IEEE80211_OFDM_RATE_6MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_9MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_12MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_18MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_24MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_36MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_48MB * 500000; - range->bitrate[i++] = IEEE80211_OFDM_RATE_54MB * 500000; - } - if (phy->type == BCM43xx_PHYTYPE_B || - phy->type == BCM43xx_PHYTYPE_G) { - range->num_bitrates += 4; - range->bitrate[i++] = IEEE80211_CCK_RATE_1MB * 500000; - range->bitrate[i++] = IEEE80211_CCK_RATE_2MB * 500000; - range->bitrate[i++] = IEEE80211_CCK_RATE_5MB * 500000; - range->bitrate[i++] = IEEE80211_CCK_RATE_11MB * 500000; - } - - geo = ieee80211_get_geo(bcm->ieee); - range->num_channels = geo->a_channels + geo->bg_channels; - j = 0; - for (i = 0; i < geo->a_channels; i++) { - if (j == IW_MAX_FREQUENCIES) - break; - range->freq[j].i = j + 1; - range->freq[j].m = geo->a[i].freq * 100000; - range->freq[j].e = 1; - j++; - } - for (i = 0; i < geo->bg_channels; i++) { - if (j == IW_MAX_FREQUENCIES) - break; - range->freq[j].i = j + 1; - range->freq[j].m = geo->bg[i].freq * 100000; - range->freq[j].e = 1; - j++; - } - range->num_frequency = j; - - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_set_nick(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - size_t len; - - mutex_lock(&bcm->mutex); - len = min((size_t)data->data.length, (size_t)IW_ESSID_MAX_SIZE); - memcpy(bcm->nick, extra, len); - bcm->nick[len] = '\0'; - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_nick(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - size_t len; - - mutex_lock(&bcm->mutex); - len = strlen(bcm->nick); - memcpy(extra, bcm->nick, len); - data->data.length = (__u16)len; - data->data.flags = 1; - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_set_rts(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int err = -EINVAL; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (data->rts.disabled) { - bcm->rts_threshold = BCM43xx_MAX_RTS_THRESHOLD; - err = 0; - } else { - if (data->rts.value >= BCM43xx_MIN_RTS_THRESHOLD && - data->rts.value <= BCM43xx_MAX_RTS_THRESHOLD) { - bcm->rts_threshold = data->rts.value; - err = 0; - } - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_rts(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - mutex_lock(&bcm->mutex); - data->rts.value = bcm->rts_threshold; - data->rts.fixed = 0; - data->rts.disabled = (bcm->rts_threshold == BCM43xx_MAX_RTS_THRESHOLD); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_set_frag(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int err = -EINVAL; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (data->frag.disabled) { - bcm->ieee->fts = MAX_FRAG_THRESHOLD; - err = 0; - } else { - if (data->frag.value >= MIN_FRAG_THRESHOLD && - data->frag.value <= MAX_FRAG_THRESHOLD) { - bcm->ieee->fts = data->frag.value & ~0x1; - err = 0; - } - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_frag(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - - mutex_lock(&bcm->mutex); - data->frag.value = bcm->ieee->fts; - data->frag.fixed = 0; - data->frag.disabled = (bcm->ieee->fts == MAX_FRAG_THRESHOLD); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_set_xmitpower(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct bcm43xx_radioinfo *radio; - struct bcm43xx_phyinfo *phy; - unsigned long flags; - int err = -ENODEV; - u16 maxpower; - - if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM) { - printk(KERN_ERR PFX "TX power not in dBm.\n"); - return -EOPNOTSUPP; - } - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) - goto out_unlock; - radio = bcm43xx_current_radio(bcm); - phy = bcm43xx_current_phy(bcm); - if (data->txpower.disabled != (!(radio->enabled))) { - if (data->txpower.disabled) - bcm43xx_radio_turn_off(bcm); - else - bcm43xx_radio_turn_on(bcm); - } - if (data->txpower.value > 0) { - /* desired and maxpower dBm values are in Q5.2 */ - if (phy->type == BCM43xx_PHYTYPE_A) - maxpower = bcm->sprom.maxpower_aphy; - else - maxpower = bcm->sprom.maxpower_bgphy; - radio->txpower_desired = limit_value(data->txpower.value << 2, - 0, maxpower); - bcm43xx_phy_xmitpower(bcm); - } - err = 0; - -out_unlock: - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_xmitpower(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct bcm43xx_radioinfo *radio; - int err = -ENODEV; - - mutex_lock(&bcm->mutex); - if (bcm43xx_status(bcm) != BCM43xx_STAT_INITIALIZED) - goto out_unlock; - radio = bcm43xx_current_radio(bcm); - /* desired dBm value is in Q5.2 */ - data->txpower.value = radio->txpower_desired >> 2; - data->txpower.fixed = 1; - data->txpower.flags = IW_TXPOW_DBM; - data->txpower.disabled = !(radio->enabled); - - err = 0; -out_unlock: - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_set_encoding(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - err = ieee80211_wx_set_encode(bcm->ieee, info, data, extra); - - return err; -} - -static int bcm43xx_wx_set_encodingext(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - err = ieee80211_wx_set_encodeext(bcm->ieee, info, data, extra); - - return err; -} - -static int bcm43xx_wx_get_encoding(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - err = ieee80211_wx_get_encode(bcm->ieee, info, data, extra); - - return err; -} - -static int bcm43xx_wx_get_encodingext(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err; - - err = ieee80211_wx_get_encodeext(bcm->ieee, info, data, extra); - - return err; -} - -static int bcm43xx_wx_set_interfmode(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int mode, err = 0; - - mode = *((int *)extra); - switch (mode) { - case 0: - mode = BCM43xx_RADIO_INTERFMODE_NONE; - break; - case 1: - mode = BCM43xx_RADIO_INTERFMODE_NONWLAN; - break; - case 2: - mode = BCM43xx_RADIO_INTERFMODE_MANUALWLAN; - break; - case 3: - mode = BCM43xx_RADIO_INTERFMODE_AUTOWLAN; - break; - default: - printk(KERN_ERR PFX "set_interfmode allowed parameters are: " - "0 => None, 1 => Non-WLAN, 2 => WLAN, " - "3 => Auto-WLAN\n"); - return -EINVAL; - } - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) { - err = bcm43xx_radio_set_interference_mitigation(bcm, mode); - if (err) { - printk(KERN_ERR PFX "Interference Mitigation not " - "supported by device\n"); - } - } else { - if (mode == BCM43xx_RADIO_INTERFMODE_AUTOWLAN) { - printk(KERN_ERR PFX "Interference Mitigation mode Auto-WLAN " - "not supported while the interface is down.\n"); - err = -ENODEV; - } else - bcm43xx_current_radio(bcm)->interfmode = mode; - } - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return err; -} - -static int bcm43xx_wx_get_interfmode(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int mode; - - mutex_lock(&bcm->mutex); - mode = bcm43xx_current_radio(bcm)->interfmode; - mutex_unlock(&bcm->mutex); - - switch (mode) { - case BCM43xx_RADIO_INTERFMODE_NONE: - strncpy(extra, "0 (No Interference Mitigation)", MAX_WX_STRING); - break; - case BCM43xx_RADIO_INTERFMODE_NONWLAN: - strncpy(extra, "1 (Non-WLAN Interference Mitigation)", MAX_WX_STRING); - break; - case BCM43xx_RADIO_INTERFMODE_MANUALWLAN: - strncpy(extra, "2 (WLAN Interference Mitigation)", MAX_WX_STRING); - break; - default: - assert(0); - } - data->data.length = strlen(extra) + 1; - - return 0; -} - -static int bcm43xx_wx_set_shortpreamble(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int on; - - on = *((int *)extra); - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - bcm->short_preamble = !!on; - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_shortpreamble(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int on; - - mutex_lock(&bcm->mutex); - on = bcm->short_preamble; - mutex_unlock(&bcm->mutex); - - if (on) - strncpy(extra, "1 (Short Preamble enabled)", MAX_WX_STRING); - else - strncpy(extra, "0 (Short Preamble disabled)", MAX_WX_STRING); - data->data.length = strlen(extra) + 1; - - return 0; -} - -static int bcm43xx_wx_set_swencryption(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - unsigned long flags; - int on; - - on = *((int *)extra); - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - bcm->ieee->host_encrypt = !!on; - bcm->ieee->host_decrypt = !!on; - bcm->ieee->host_build_iv = !on; - bcm->ieee->host_strip_iv_icv = !on; - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - - return 0; -} - -static int bcm43xx_wx_get_swencryption(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int on; - - mutex_lock(&bcm->mutex); - on = bcm->ieee->host_encrypt; - mutex_unlock(&bcm->mutex); - - if (on) - strncpy(extra, "1 (SW encryption enabled) ", MAX_WX_STRING); - else - strncpy(extra, "0 (SW encryption disabled) ", MAX_WX_STRING); - data->data.length = strlen(extra + 1); - - return 0; -} - -/* Enough buffer to hold a hexdump of the sprom data. */ -#define SPROM_BUFFERSIZE 512 - -static int sprom2hex(const u16 *sprom, char *dump) -{ - int i, pos = 0; - - for (i = 0; i < BCM43xx_SPROM_SIZE; i++) { - pos += snprintf(dump + pos, SPROM_BUFFERSIZE - pos - 1, - "%04X", swab16(sprom[i]) & 0xFFFF); - } - - return pos + 1; -} - -static int hex2sprom(u16 *sprom, const char *dump, unsigned int len) -{ - char tmp[5] = { 0 }; - int cnt = 0; - unsigned long parsed; - - if (len < BCM43xx_SPROM_SIZE * sizeof(u16) * 2) - return -EINVAL; - while (cnt < BCM43xx_SPROM_SIZE) { - memcpy(tmp, dump, 4); - dump += 4; - parsed = simple_strtoul(tmp, NULL, 16); - sprom[cnt++] = swab16((u16)parsed); - } - - return 0; -} - -static int bcm43xx_wx_sprom_read(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = -EPERM; - u16 *sprom; - unsigned long flags; - - if (!capable(CAP_SYS_RAWIO)) - goto out; - - err = -ENOMEM; - sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), - GFP_KERNEL); - if (!sprom) - goto out; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - err = -ENODEV; - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) - err = bcm43xx_sprom_read(bcm, sprom); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); - if (!err) - data->data.length = sprom2hex(sprom, extra); - kfree(sprom); -out: - return err; -} - -static int bcm43xx_wx_sprom_write(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - int err = -EPERM; - u16 *sprom; - unsigned long flags; - char *input; - unsigned int len; - - if (!capable(CAP_SYS_RAWIO)) - goto out; - - err = -ENOMEM; - sprom = kmalloc(BCM43xx_SPROM_SIZE * sizeof(*sprom), - GFP_KERNEL); - if (!sprom) - goto out; - - len = data->data.length; - extra[len - 1] = '\0'; - input = strchr(extra, ':'); - if (input) { - input++; - len -= input - extra; - } else - input = extra; - err = hex2sprom(sprom, input, len); - if (err) - goto out_kfree; - - mutex_lock(&bcm->mutex); - spin_lock_irqsave(&bcm->irq_lock, flags); - spin_lock(&bcm->leds_lock); - err = -ENODEV; - if (bcm43xx_status(bcm) == BCM43xx_STAT_INITIALIZED) - err = bcm43xx_sprom_write(bcm, sprom); - spin_unlock(&bcm->leds_lock); - spin_unlock_irqrestore(&bcm->irq_lock, flags); - mutex_unlock(&bcm->mutex); -out_kfree: - kfree(sprom); -out: - return err; -} - -/* Get wireless statistics. Called by /proc/net/wireless and by SIOCGIWSTATS */ - -static struct iw_statistics *bcm43xx_get_wireless_stats(struct net_device *net_dev) -{ - struct bcm43xx_private *bcm = bcm43xx_priv(net_dev); - struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - struct iw_statistics *wstats; - struct ieee80211_network *network = NULL; - static int tmp_level = 0; - static int tmp_qual = 0; - unsigned long flags; - - wstats = &bcm->stats.wstats; - if (!mac->associnfo.associated) { - wstats->miss.beacon = 0; -// bcm->ieee->ieee_stats.tx_retry_limit_exceeded = 0; // FIXME: should this be cleared here? - wstats->discard.retries = 0; -// bcm->ieee->ieee_stats.tx_discards_wrong_sa = 0; // FIXME: same question - wstats->discard.nwid = 0; -// bcm->ieee->ieee_stats.rx_discards_undecryptable = 0; // FIXME: ditto - wstats->discard.code = 0; -// bcm->ieee->ieee_stats.rx_fragments = 0; // FIXME: same here - wstats->discard.fragment = 0; - wstats->discard.misc = 0; - wstats->qual.qual = 0; - wstats->qual.level = 0; - wstats->qual.noise = 0; - wstats->qual.updated = 7; - wstats->qual.updated |= IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - return wstats; - } - /* fill in the real statistics when iface associated */ - spin_lock_irqsave(&mac->ieee->lock, flags); - list_for_each_entry(network, &mac->ieee->network_list, list) { - if (!memcmp(mac->associnfo.bssid, network->bssid, ETH_ALEN)) { - if (!tmp_level) { /* get initial values */ - tmp_level = network->stats.signal; - tmp_qual = network->stats.rssi; - } else { /* smooth results */ - tmp_level = (15 * tmp_level + network->stats.signal)/16; - tmp_qual = (15 * tmp_qual + network->stats.rssi)/16; - } - break; - } - } - spin_unlock_irqrestore(&mac->ieee->lock, flags); - wstats->qual.level = tmp_level; - wstats->qual.qual = 100 * tmp_qual / RX_RSSI_MAX; - wstats->qual.noise = bcm->stats.noise; - wstats->qual.updated = IW_QUAL_ALL_UPDATED | IW_QUAL_DBM; - wstats->discard.code = bcm->ieee->ieee_stats.rx_discards_undecryptable; - wstats->discard.retries = bcm->ieee->ieee_stats.tx_retry_limit_exceeded; - wstats->discard.nwid = bcm->ieee->ieee_stats.tx_discards_wrong_sa; - wstats->discard.fragment = bcm->ieee->ieee_stats.rx_fragments; - wstats->discard.misc = 0; // FIXME - wstats->miss.beacon = 0; // FIXME - return wstats; -} - - -#ifdef WX -# undef WX -#endif -#define WX(ioctl) [(ioctl) - SIOCSIWCOMMIT] -static const iw_handler bcm43xx_wx_handlers[] = { - /* Wireless Identification */ - WX(SIOCGIWNAME) = bcm43xx_wx_get_name, - /* Basic operations */ - WX(SIOCSIWFREQ) = bcm43xx_wx_set_channelfreq, - WX(SIOCGIWFREQ) = bcm43xx_wx_get_channelfreq, - WX(SIOCSIWMODE) = bcm43xx_wx_set_mode, - WX(SIOCGIWMODE) = bcm43xx_wx_get_mode, - /* Informative stuff */ - WX(SIOCGIWRANGE) = bcm43xx_wx_get_rangeparams, - /* Access Point manipulation */ - WX(SIOCSIWAP) = ieee80211softmac_wx_set_wap, - WX(SIOCGIWAP) = ieee80211softmac_wx_get_wap, - WX(SIOCSIWSCAN) = ieee80211softmac_wx_trigger_scan, - WX(SIOCGIWSCAN) = ieee80211softmac_wx_get_scan_results, - /* 802.11 specific support */ - WX(SIOCSIWESSID) = ieee80211softmac_wx_set_essid, - WX(SIOCGIWESSID) = ieee80211softmac_wx_get_essid, - WX(SIOCSIWNICKN) = bcm43xx_wx_set_nick, - WX(SIOCGIWNICKN) = bcm43xx_wx_get_nick, - /* Other parameters */ - WX(SIOCSIWRATE) = ieee80211softmac_wx_set_rate, - WX(SIOCGIWRATE) = ieee80211softmac_wx_get_rate, - WX(SIOCSIWRTS) = bcm43xx_wx_set_rts, - WX(SIOCGIWRTS) = bcm43xx_wx_get_rts, - WX(SIOCSIWFRAG) = bcm43xx_wx_set_frag, - WX(SIOCGIWFRAG) = bcm43xx_wx_get_frag, - WX(SIOCSIWTXPOW) = bcm43xx_wx_set_xmitpower, - WX(SIOCGIWTXPOW) = bcm43xx_wx_get_xmitpower, -//TODO WX(SIOCSIWRETRY) = bcm43xx_wx_set_retry, -//TODO WX(SIOCGIWRETRY) = bcm43xx_wx_get_retry, - /* Encoding */ - WX(SIOCSIWENCODE) = bcm43xx_wx_set_encoding, - WX(SIOCGIWENCODE) = bcm43xx_wx_get_encoding, - WX(SIOCSIWENCODEEXT) = bcm43xx_wx_set_encodingext, - WX(SIOCGIWENCODEEXT) = bcm43xx_wx_get_encodingext, - /* Power saving */ -//TODO WX(SIOCSIWPOWER) = bcm43xx_wx_set_power, -//TODO WX(SIOCGIWPOWER) = bcm43xx_wx_get_power, - WX(SIOCSIWGENIE) = ieee80211softmac_wx_set_genie, - WX(SIOCGIWGENIE) = ieee80211softmac_wx_get_genie, - WX(SIOCSIWAUTH) = ieee80211_wx_set_auth, - WX(SIOCGIWAUTH) = ieee80211_wx_get_auth, -}; -#undef WX - -static const iw_handler bcm43xx_priv_wx_handlers[] = { - /* Set Interference Mitigation Mode. */ - bcm43xx_wx_set_interfmode, - /* Get Interference Mitigation Mode. */ - bcm43xx_wx_get_interfmode, - /* Enable/Disable Short Preamble mode. */ - bcm43xx_wx_set_shortpreamble, - /* Get Short Preamble mode. */ - bcm43xx_wx_get_shortpreamble, - /* Enable/Disable Software Encryption mode */ - bcm43xx_wx_set_swencryption, - /* Get Software Encryption mode */ - bcm43xx_wx_get_swencryption, - /* Write SRPROM data. */ - bcm43xx_wx_sprom_write, - /* Read SPROM data. */ - bcm43xx_wx_sprom_read, -}; - -#define PRIV_WX_SET_INTERFMODE (SIOCIWFIRSTPRIV + 0) -#define PRIV_WX_GET_INTERFMODE (SIOCIWFIRSTPRIV + 1) -#define PRIV_WX_SET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 2) -#define PRIV_WX_GET_SHORTPREAMBLE (SIOCIWFIRSTPRIV + 3) -#define PRIV_WX_SET_SWENCRYPTION (SIOCIWFIRSTPRIV + 4) -#define PRIV_WX_GET_SWENCRYPTION (SIOCIWFIRSTPRIV + 5) -#define PRIV_WX_SPROM_WRITE (SIOCIWFIRSTPRIV + 6) -#define PRIV_WX_SPROM_READ (SIOCIWFIRSTPRIV + 7) - -#define PRIV_WX_DUMMY(ioctl) \ - { \ - .cmd = (ioctl), \ - .name = "__unused" \ - } - -static const struct iw_priv_args bcm43xx_priv_wx_args[] = { - { - .cmd = PRIV_WX_SET_INTERFMODE, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_interfmode", - }, - { - .cmd = PRIV_WX_GET_INTERFMODE, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - .name = "get_interfmode", - }, - { - .cmd = PRIV_WX_SET_SHORTPREAMBLE, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_shortpreamb", - }, - { - .cmd = PRIV_WX_GET_SHORTPREAMBLE, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - .name = "get_shortpreamb", - }, - { - .cmd = PRIV_WX_SET_SWENCRYPTION, - .set_args = IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, - .name = "set_swencrypt", - }, - { - .cmd = PRIV_WX_GET_SWENCRYPTION, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | MAX_WX_STRING, - .name = "get_swencrypt", - }, - { - .cmd = PRIV_WX_SPROM_WRITE, - .set_args = IW_PRIV_TYPE_CHAR | SPROM_BUFFERSIZE, - .name = "write_sprom", - }, - { - .cmd = PRIV_WX_SPROM_READ, - .get_args = IW_PRIV_TYPE_CHAR | IW_PRIV_SIZE_FIXED | SPROM_BUFFERSIZE, - .name = "read_sprom", - }, -}; - -const struct iw_handler_def bcm43xx_wx_handlers_def = { - .standard = bcm43xx_wx_handlers, - .num_standard = ARRAY_SIZE(bcm43xx_wx_handlers), - .num_private = ARRAY_SIZE(bcm43xx_priv_wx_handlers), - .num_private_args = ARRAY_SIZE(bcm43xx_priv_wx_args), - .private = bcm43xx_priv_wx_handlers, - .private_args = bcm43xx_priv_wx_args, - .get_wireless_stats = bcm43xx_get_wireless_stats, -}; diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h b/drivers/net/wireless/bcm43xx/bcm43xx_wx.h deleted file mode 100644 index 1f29ff3aa4c3..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_wx.h +++ /dev/null @@ -1,36 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - Some parts of the code in this file are derived from the ipw2200 - driver Copyright(c) 2003 - 2004 Intel Corporation. - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#ifndef BCM43xx_WX_H_ -#define BCM43xx_WX_H_ - -extern const struct iw_handler_def bcm43xx_wx_handlers_def; - -#endif /* BCM43xx_WX_H_ */ diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c deleted file mode 100644 index f79fe11f9e81..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.c +++ /dev/null @@ -1,565 +0,0 @@ -/* - - Broadcom BCM43xx wireless driver - - Transmission (TX/RX) related functions. - - Copyright (c) 2005 Martin Langer , - Stefano Brivio - Michael Buesch - Danny van Dyk - Andreas Jaggi - - 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; see the file COPYING. If not, write to - the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, - Boston, MA 02110-1301, USA. - -*/ - -#include "bcm43xx_xmit.h" - -#include - - -/* Extract the bitrate out of a CCK PLCP header. */ -static u8 bcm43xx_plcp_get_bitrate_cck(struct bcm43xx_plcp_hdr4 *plcp) -{ - switch (plcp->raw[0]) { - case 0x0A: - return IEEE80211_CCK_RATE_1MB; - case 0x14: - return IEEE80211_CCK_RATE_2MB; - case 0x37: - return IEEE80211_CCK_RATE_5MB; - case 0x6E: - return IEEE80211_CCK_RATE_11MB; - } - assert(0); - return 0; -} - -/* Extract the bitrate out of an OFDM PLCP header. */ -static u8 bcm43xx_plcp_get_bitrate_ofdm(struct bcm43xx_plcp_hdr4 *plcp) -{ - switch (plcp->raw[0] & 0xF) { - case 0xB: - return IEEE80211_OFDM_RATE_6MB; - case 0xF: - return IEEE80211_OFDM_RATE_9MB; - case 0xA: - return IEEE80211_OFDM_RATE_12MB; - case 0xE: - return IEEE80211_OFDM_RATE_18MB; - case 0x9: - return IEEE80211_OFDM_RATE_24MB; - case 0xD: - return IEEE80211_OFDM_RATE_36MB; - case 0x8: - return IEEE80211_OFDM_RATE_48MB; - case 0xC: - return IEEE80211_OFDM_RATE_54MB; - } - assert(0); - return 0; -} - -u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_CCK_RATE_1MB: - return 0x0A; - case IEEE80211_CCK_RATE_2MB: - return 0x14; - case IEEE80211_CCK_RATE_5MB: - return 0x37; - case IEEE80211_CCK_RATE_11MB: - return 0x6E; - } - assert(0); - return 0; -} - -u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_OFDM_RATE_6MB: - return 0xB; - case IEEE80211_OFDM_RATE_9MB: - return 0xF; - case IEEE80211_OFDM_RATE_12MB: - return 0xA; - case IEEE80211_OFDM_RATE_18MB: - return 0xE; - case IEEE80211_OFDM_RATE_24MB: - return 0x9; - case IEEE80211_OFDM_RATE_36MB: - return 0xD; - case IEEE80211_OFDM_RATE_48MB: - return 0x8; - case IEEE80211_OFDM_RATE_54MB: - return 0xC; - } - assert(0); - return 0; -} - -static void bcm43xx_generate_plcp_hdr(struct bcm43xx_plcp_hdr4 *plcp, - const u16 octets, const u8 bitrate, - const int ofdm_modulation) -{ - __le32 *data = &(plcp->data); - __u8 *raw = plcp->raw; - - if (ofdm_modulation) { - u32 val = bcm43xx_plcp_get_ratecode_ofdm(bitrate); - assert(!(octets & 0xF000)); - val |= (octets << 5); - *data = cpu_to_le32(val); - } else { - u32 plen; - - plen = octets * 16 / bitrate; - if ((octets * 16 % bitrate) > 0) { - plen++; - if ((bitrate == IEEE80211_CCK_RATE_11MB) - && ((octets * 8 % 11) < 4)) { - raw[1] = 0x84; - } else - raw[1] = 0x04; - } else - raw[1] = 0x04; - *data |= cpu_to_le32(plen << 16); - raw[0] = bcm43xx_plcp_get_ratecode_cck(bitrate); - } -} - -static u8 bcm43xx_calc_fallback_rate(u8 bitrate) -{ - switch (bitrate) { - case IEEE80211_CCK_RATE_1MB: - return IEEE80211_CCK_RATE_1MB; - case IEEE80211_CCK_RATE_2MB: - return IEEE80211_CCK_RATE_1MB; - case IEEE80211_CCK_RATE_5MB: - return IEEE80211_CCK_RATE_2MB; - case IEEE80211_CCK_RATE_11MB: - return IEEE80211_CCK_RATE_5MB; - case IEEE80211_OFDM_RATE_6MB: - return IEEE80211_CCK_RATE_5MB; - case IEEE80211_OFDM_RATE_9MB: - return IEEE80211_OFDM_RATE_6MB; - case IEEE80211_OFDM_RATE_12MB: - return IEEE80211_OFDM_RATE_9MB; - case IEEE80211_OFDM_RATE_18MB: - return IEEE80211_OFDM_RATE_12MB; - case IEEE80211_OFDM_RATE_24MB: - return IEEE80211_OFDM_RATE_18MB; - case IEEE80211_OFDM_RATE_36MB: - return IEEE80211_OFDM_RATE_24MB; - case IEEE80211_OFDM_RATE_48MB: - return IEEE80211_OFDM_RATE_36MB; - case IEEE80211_OFDM_RATE_54MB: - return IEEE80211_OFDM_RATE_48MB; - } - assert(0); - return 0; -} - -static -__le16 bcm43xx_calc_duration_id(const struct ieee80211_hdr *wireless_header, - u8 bitrate) -{ - const u16 frame_ctl = le16_to_cpu(wireless_header->frame_ctl); - __le16 duration_id = wireless_header->duration_id; - - switch (WLAN_FC_GET_TYPE(frame_ctl)) { - case IEEE80211_FTYPE_DATA: - case IEEE80211_FTYPE_MGMT: - //TODO: Steal the code from ieee80211, once it is completed there. - break; - case IEEE80211_FTYPE_CTL: - /* Use the original duration/id. */ - break; - default: - assert(0); - } - - return duration_id; -} - -static inline -u16 ceiling_div(u16 dividend, u16 divisor) -{ - return ((dividend + divisor - 1) / divisor); -} - -static void bcm43xx_generate_rts(const struct bcm43xx_phyinfo *phy, - struct bcm43xx_txhdr *txhdr, - u16 *flags, - u8 bitrate, - const struct ieee80211_hdr_4addr *wlhdr) -{ - u16 fctl; - u16 dur; - u8 fallback_bitrate; - int ofdm_modulation; - int fallback_ofdm_modulation; -// u8 *sa, *da; - u16 flen; - -//FIXME sa = ieee80211_get_SA((struct ieee80211_hdr *)wlhdr); -//FIXME da = ieee80211_get_DA((struct ieee80211_hdr *)wlhdr); - fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); - ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); - fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); - - flen = sizeof(u16) + sizeof(u16) + ETH_ALEN + ETH_ALEN + IEEE80211_FCS_LEN, - bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_plcp), - flen, bitrate, - !ieee80211_is_cck_rate(bitrate)); - bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->rts_cts_fallback_plcp), - flen, fallback_bitrate, - !ieee80211_is_cck_rate(fallback_bitrate)); - fctl = IEEE80211_FTYPE_CTL; - fctl |= IEEE80211_STYPE_RTS; - dur = le16_to_cpu(wlhdr->duration_id); -/*FIXME: should we test for dur==0 here and let it unmodified in this case? - * The following assert checks for this case... - */ -assert(dur); -/*FIXME: The duration calculation is not really correct. - * I am not 100% sure which bitrate to use. We use the RTS rate here, - * but this is likely to be wrong. - */ - if (phy->type == BCM43xx_PHYTYPE_A) { - /* Three times SIFS */ - dur += 16 * 3; - /* Add ACK duration. */ - dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10, - bitrate * 4); - /* Add CTS duration. */ - dur += ceiling_div((16 + 8 * (14 /*bytes*/) + 6) * 10, - bitrate * 4); - } else { - /* Three times SIFS */ - dur += 10 * 3; - /* Add ACK duration. */ - dur += ceiling_div(8 * (14 /*bytes*/) * 10, - bitrate); - /* Add CTS duration. */ - dur += ceiling_div(8 * (14 /*bytes*/) * 10, - bitrate); - } - - txhdr->rts_cts_frame_control = cpu_to_le16(fctl); - txhdr->rts_cts_dur = cpu_to_le16(dur); -//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(wlhdr->addr1), BCM43xx_MACARG(wlhdr->addr2), BCM43xx_MACARG(wlhdr->addr3)); -//printk(BCM43xx_MACFMT " " BCM43xx_MACFMT "\n", BCM43xx_MACARG(sa), BCM43xx_MACARG(da)); - memcpy(txhdr->rts_cts_mac1, wlhdr->addr1, ETH_ALEN);//FIXME! -// memcpy(txhdr->rts_cts_mac2, sa, ETH_ALEN); - - *flags |= BCM43xx_TXHDRFLAG_RTSCTS; - *flags |= BCM43xx_TXHDRFLAG_RTS; - if (ofdm_modulation) - *flags |= BCM43xx_TXHDRFLAG_RTSCTS_OFDM; - if (fallback_ofdm_modulation) - *flags |= BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM; -} - -void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - const unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie) -{ - const struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - const struct ieee80211_hdr_4addr *wireless_header = (const struct ieee80211_hdr_4addr *)fragment_data; - const struct ieee80211_security *secinfo = &bcm->ieee->sec; - u8 bitrate; - u8 fallback_bitrate; - int ofdm_modulation; - int fallback_ofdm_modulation; - u16 plcp_fragment_len = fragment_len; - u16 flags = 0; - u16 control = 0; - u16 wsec_rate = 0; - u16 encrypt_frame; - const u16 ftype = WLAN_FC_GET_TYPE(le16_to_cpu(wireless_header->frame_ctl)); - const int is_mgt = (ftype == IEEE80211_FTYPE_MGMT); - - /* Now construct the TX header. */ - memset(txhdr, 0, sizeof(*txhdr)); - - bitrate = ieee80211softmac_suggest_txrate(bcm->softmac, - is_multicast_ether_addr(wireless_header->addr1), is_mgt); - ofdm_modulation = !(ieee80211_is_cck_rate(bitrate)); - fallback_bitrate = bcm43xx_calc_fallback_rate(bitrate); - fallback_ofdm_modulation = !(ieee80211_is_cck_rate(fallback_bitrate)); - - /* Set Frame Control from 80211 header. */ - txhdr->frame_control = wireless_header->frame_ctl; - /* Copy address1 from 80211 header. */ - memcpy(txhdr->mac1, wireless_header->addr1, 6); - /* Set the fallback duration ID. */ - txhdr->fallback_dur_id = bcm43xx_calc_duration_id((const struct ieee80211_hdr *)wireless_header, - fallback_bitrate); - /* Set the cookie (used as driver internal ID for the frame) */ - txhdr->cookie = cpu_to_le16(cookie); - - /* Hardware appends FCS. */ - plcp_fragment_len += IEEE80211_FCS_LEN; - - /* Hardware encryption. */ - encrypt_frame = le16_to_cpup(&wireless_header->frame_ctl) & IEEE80211_FCTL_PROTECTED; - if (encrypt_frame && !bcm->ieee->host_encrypt) { - const struct ieee80211_hdr_3addr *hdr = (struct ieee80211_hdr_3addr *)wireless_header; - memcpy(txhdr->wep_iv, hdr->payload, 4); - /* Hardware appends ICV. */ - plcp_fragment_len += 4; - - wsec_rate |= (bcm->key[secinfo->active_key].algorithm << BCM43xx_TXHDR_WSEC_ALGO_SHIFT) - & BCM43xx_TXHDR_WSEC_ALGO_MASK; - wsec_rate |= (secinfo->active_key << BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT) - & BCM43xx_TXHDR_WSEC_KEYINDEX_MASK; - } - - /* Generate the PLCP header and the fallback PLCP header. */ - bcm43xx_generate_plcp_hdr((struct bcm43xx_plcp_hdr4 *)(&txhdr->plcp), - plcp_fragment_len, - bitrate, ofdm_modulation); - bcm43xx_generate_plcp_hdr(&txhdr->fallback_plcp, plcp_fragment_len, - fallback_bitrate, fallback_ofdm_modulation); - - /* Set the CONTROL field */ - if (ofdm_modulation) - control |= BCM43xx_TXHDRCTL_OFDM; - if (bcm->short_preamble) //FIXME: could be the other way around, please test - control |= BCM43xx_TXHDRCTL_SHORT_PREAMBLE; - control |= (phy->antenna_diversity << BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT) - & BCM43xx_TXHDRCTL_ANTENNADIV_MASK; - - /* Set the FLAGS field */ - if (!is_multicast_ether_addr(wireless_header->addr1) && - !is_broadcast_ether_addr(wireless_header->addr1)) - flags |= BCM43xx_TXHDRFLAG_EXPECTACK; - if (1 /* FIXME: PS poll?? */) - flags |= 0x10; // FIXME: unknown meaning. - if (fallback_ofdm_modulation) - flags |= BCM43xx_TXHDRFLAG_FALLBACKOFDM; - if (is_first_fragment) - flags |= BCM43xx_TXHDRFLAG_FIRSTFRAGMENT; - - /* Set WSEC/RATE field */ - wsec_rate |= (txhdr->plcp.raw[0] << BCM43xx_TXHDR_RATE_SHIFT) - & BCM43xx_TXHDR_RATE_MASK; - - /* Generate the RTS/CTS packet, if required. */ - /* FIXME: We should first try with CTS-to-self, - * if we are on 80211g. If we get too many - * failures (hidden nodes), we should switch back to RTS/CTS. - */ - if (0/*FIXME txctl->use_rts_cts*/) { - bcm43xx_generate_rts(phy, txhdr, &flags, - 0/*FIXME txctl->rts_cts_rate*/, - wireless_header); - } - - txhdr->flags = cpu_to_le16(flags); - txhdr->control = cpu_to_le16(control); - txhdr->wsec_rate = cpu_to_le16(wsec_rate); -} - -static s8 bcm43xx_rssi_postprocess(struct bcm43xx_private *bcm, - u8 in_rssi, int ofdm, - int adjust_2053, int adjust_2050) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - s32 tmp; - - switch (radio->version) { - case 0x2050: - if (ofdm) { - tmp = in_rssi; - if (tmp > 127) - tmp -= 256; - tmp *= 73; - tmp /= 64; - if (adjust_2050) - tmp += 25; - else - tmp -= 3; - } else { - if (bcm->sprom.boardflags & BCM43xx_BFL_RSSI) { - if (in_rssi > 63) - in_rssi = 63; - tmp = radio->nrssi_lt[in_rssi]; - tmp = 31 - tmp; - tmp *= -131; - tmp /= 128; - tmp -= 57; - } else { - tmp = in_rssi; - tmp = 31 - tmp; - tmp *= -149; - tmp /= 128; - tmp -= 68; - } - if (phy->type == BCM43xx_PHYTYPE_G && - adjust_2050) - tmp += 25; - } - break; - case 0x2060: - if (in_rssi > 127) - tmp = in_rssi - 256; - else - tmp = in_rssi; - break; - default: - tmp = in_rssi; - tmp -= 11; - tmp *= 103; - tmp /= 64; - if (adjust_2053) - tmp -= 109; - else - tmp -= 83; - } - - return (s8)tmp; -} - -//TODO -#if 0 -static s8 bcm43xx_rssinoise_postprocess(struct bcm43xx_private *bcm, - u8 in_rssi) -{ - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - s8 ret; - - if (phy->type == BCM43xx_PHYTYPE_A) { - //TODO: Incomplete specs. - ret = 0; - } else - ret = bcm43xx_rssi_postprocess(bcm, in_rssi, 0, 1, 1); - - return ret; -} -#endif - -int bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr) -{ - struct bcm43xx_radioinfo *radio = bcm43xx_current_radio(bcm); - struct bcm43xx_phyinfo *phy = bcm43xx_current_phy(bcm); - struct bcm43xx_plcp_hdr4 *plcp; - struct ieee80211_rx_stats stats; - struct ieee80211_hdr_4addr *wlhdr; - u16 frame_ctl; - int is_packet_for_us = 0; - int err = -EINVAL; - const u16 rxflags1 = le16_to_cpu(rxhdr->flags1); - const u16 rxflags2 = le16_to_cpu(rxhdr->flags2); - const u16 rxflags3 = le16_to_cpu(rxhdr->flags3); - const int is_ofdm = !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_OFDM); - - if (rxflags2 & BCM43xx_RXHDR_FLAGS2_TYPE2FRAME) { - plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data + 2); - /* Skip two unknown bytes and the PLCP header. */ - skb_pull(skb, 2 + sizeof(struct bcm43xx_plcp_hdr6)); - } else { - plcp = (struct bcm43xx_plcp_hdr4 *)(skb->data); - /* Skip the PLCP header. */ - skb_pull(skb, sizeof(struct bcm43xx_plcp_hdr6)); - } - /* The SKB contains the PAYLOAD (wireless header + data) - * at this point. The FCS at the end is stripped. - */ - - memset(&stats, 0, sizeof(stats)); - stats.mac_time = le16_to_cpu(rxhdr->mactime); - stats.rssi = rxhdr->rssi; - stats.signal = bcm43xx_rssi_postprocess(bcm, rxhdr->rssi, is_ofdm, - !!(rxflags1 & BCM43xx_RXHDR_FLAGS1_2053RSSIADJ), - !!(rxflags3 & BCM43xx_RXHDR_FLAGS3_2050RSSIADJ)); - stats.noise = bcm->stats.noise; - if (is_ofdm) - stats.rate = bcm43xx_plcp_get_bitrate_ofdm(plcp); - else - stats.rate = bcm43xx_plcp_get_bitrate_cck(plcp); - stats.received_channel = radio->channel; - stats.mask = IEEE80211_STATMASK_SIGNAL | - IEEE80211_STATMASK_NOISE | - IEEE80211_STATMASK_RATE | - IEEE80211_STATMASK_RSSI; - if (phy->type == BCM43xx_PHYTYPE_A) - stats.freq = IEEE80211_52GHZ_BAND; - else - stats.freq = IEEE80211_24GHZ_BAND; - stats.len = skb->len; - - bcm->stats.last_rx = jiffies; - if (bcm->ieee->iw_mode == IW_MODE_MONITOR) { - err = ieee80211_rx(bcm->ieee, skb, &stats); - return (err == 0) ? -EINVAL : 0; - } - - wlhdr = (struct ieee80211_hdr_4addr *)(skb->data); - - switch (bcm->ieee->iw_mode) { - case IW_MODE_ADHOC: - if (memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || - memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || - is_broadcast_ether_addr(wlhdr->addr1) || - is_multicast_ether_addr(wlhdr->addr1) || - bcm->net_dev->flags & IFF_PROMISC) - is_packet_for_us = 1; - break; - case IW_MODE_INFRA: - default: - /* When receiving multicast or broadcast packets, filter out - the packets we send ourself; we shouldn't see those */ - if (memcmp(wlhdr->addr3, bcm->ieee->bssid, ETH_ALEN) == 0 || - memcmp(wlhdr->addr1, bcm->net_dev->dev_addr, ETH_ALEN) == 0 || - (memcmp(wlhdr->addr3, bcm->net_dev->dev_addr, ETH_ALEN) && - (is_broadcast_ether_addr(wlhdr->addr1) || - is_multicast_ether_addr(wlhdr->addr1) || - bcm->net_dev->flags & IFF_PROMISC))) - is_packet_for_us = 1; - break; - } - - frame_ctl = le16_to_cpu(wlhdr->frame_ctl); - switch (WLAN_FC_GET_TYPE(frame_ctl)) { - case IEEE80211_FTYPE_MGMT: - ieee80211_rx_mgt(bcm->ieee, wlhdr, &stats); - break; - case IEEE80211_FTYPE_DATA: - if (is_packet_for_us) { - err = ieee80211_rx(bcm->ieee, skb, &stats); - err = (err == 0) ? -EINVAL : 0; - } - break; - case IEEE80211_FTYPE_CTL: - break; - default: - assert(0); - return -EINVAL; - } - - return err; -} diff --git a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h b/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h deleted file mode 100644 index 47c135a7f4dc..000000000000 --- a/drivers/net/wireless/bcm43xx/bcm43xx_xmit.h +++ /dev/null @@ -1,150 +0,0 @@ -#ifndef BCM43xx_XMIT_H_ -#define BCM43xx_XMIT_H_ - -#include "bcm43xx_main.h" - - -#define _bcm43xx_declare_plcp_hdr(size) \ - struct bcm43xx_plcp_hdr##size { \ - union { \ - __le32 data; \ - __u8 raw[size]; \ - } __attribute__((__packed__)); \ - } __attribute__((__packed__)) - -/* struct bcm43xx_plcp_hdr4 */ -_bcm43xx_declare_plcp_hdr(4); -/* struct bcm43xx_plcp_hdr6 */ -_bcm43xx_declare_plcp_hdr(6); - -#undef _bcm43xx_declare_plcp_hdr - -/* Device specific TX header. To be prepended to TX frames. */ -struct bcm43xx_txhdr { - union { - struct { - __le16 flags; - __le16 wsec_rate; - __le16 frame_control; - u16 unknown_zeroed_0; - __le16 control; - u8 wep_iv[10]; - u8 unknown_wsec_tkip_data[3]; //FIXME - PAD_BYTES(3); - u8 mac1[6]; - u16 unknown_zeroed_1; - struct bcm43xx_plcp_hdr4 rts_cts_fallback_plcp; - __le16 rts_cts_dur_fallback; - struct bcm43xx_plcp_hdr4 fallback_plcp; - __le16 fallback_dur_id; - PAD_BYTES(2); - __le16 cookie; - __le16 unknown_scb_stuff; //FIXME - struct bcm43xx_plcp_hdr6 rts_cts_plcp; - __le16 rts_cts_frame_control; - __le16 rts_cts_dur; - u8 rts_cts_mac1[6]; - u8 rts_cts_mac2[6]; - PAD_BYTES(2); - struct bcm43xx_plcp_hdr6 plcp; - } __attribute__((__packed__)); - u8 raw[82]; - } __attribute__((__packed__)); -} __attribute__((__packed__)); - -/* Values/Masks for the device TX header */ -#define BCM43xx_TXHDRFLAG_EXPECTACK 0x0001 -#define BCM43xx_TXHDRFLAG_RTSCTS 0x0002 -#define BCM43xx_TXHDRFLAG_RTS 0x0004 -#define BCM43xx_TXHDRFLAG_FIRSTFRAGMENT 0x0008 -#define BCM43xx_TXHDRFLAG_DESTPSMODE 0x0020 -#define BCM43xx_TXHDRFLAG_RTSCTS_OFDM 0x0080 -#define BCM43xx_TXHDRFLAG_FALLBACKOFDM 0x0100 -#define BCM43xx_TXHDRFLAG_RTSCTSFALLBACK_OFDM 0x0200 -#define BCM43xx_TXHDRFLAG_CTS 0x0400 -#define BCM43xx_TXHDRFLAG_FRAMEBURST 0x0800 - -#define BCM43xx_TXHDRCTL_OFDM 0x0001 -#define BCM43xx_TXHDRCTL_SHORT_PREAMBLE 0x0010 -#define BCM43xx_TXHDRCTL_ANTENNADIV_MASK 0x0030 -#define BCM43xx_TXHDRCTL_ANTENNADIV_SHIFT 8 - -#define BCM43xx_TXHDR_RATE_MASK 0x0F00 -#define BCM43xx_TXHDR_RATE_SHIFT 8 -#define BCM43xx_TXHDR_RTSRATE_MASK 0xF000 -#define BCM43xx_TXHDR_RTSRATE_SHIFT 12 -#define BCM43xx_TXHDR_WSEC_KEYINDEX_MASK 0x00F0 -#define BCM43xx_TXHDR_WSEC_KEYINDEX_SHIFT 4 -#define BCM43xx_TXHDR_WSEC_ALGO_MASK 0x0003 -#define BCM43xx_TXHDR_WSEC_ALGO_SHIFT 0 - -void bcm43xx_generate_txhdr(struct bcm43xx_private *bcm, - struct bcm43xx_txhdr *txhdr, - const unsigned char *fragment_data, - const unsigned int fragment_len, - const int is_first_fragment, - const u16 cookie); - -/* RX header as received from the hardware. */ -struct bcm43xx_rxhdr { - /* Frame Length. Must be generated explicitly in PIO mode. */ - __le16 frame_length; - PAD_BYTES(2); - /* Flags field 1 */ - __le16 flags1; - u8 rssi; - u8 signal_quality; - PAD_BYTES(2); - /* Flags field 3 */ - __le16 flags3; - /* Flags field 2 */ - __le16 flags2; - /* Lower 16bits of the TSF at the time the frame started. */ - __le16 mactime; - PAD_BYTES(14); -} __attribute__((__packed__)); - -#define BCM43xx_RXHDR_FLAGS1_OFDM (1 << 0) -/*#define BCM43xx_RXHDR_FLAGS1_SIGNAL??? (1 << 3) FIXME */ -#define BCM43xx_RXHDR_FLAGS1_SHORTPREAMBLE (1 << 7) -#define BCM43xx_RXHDR_FLAGS1_2053RSSIADJ (1 << 14) - -#define BCM43xx_RXHDR_FLAGS2_INVALIDFRAME (1 << 0) -#define BCM43xx_RXHDR_FLAGS2_TYPE2FRAME (1 << 2) -/*FIXME: WEP related flags */ - -#define BCM43xx_RXHDR_FLAGS3_2050RSSIADJ (1 << 10) - -/* Transmit Status as received from the hardware. */ -struct bcm43xx_hwxmitstatus { - PAD_BYTES(4); - __le16 cookie; - u8 flags; - u8 cnt1:4, - cnt2:4; - PAD_BYTES(2); - __le16 seq; - __le16 unknown; //FIXME -} __attribute__((__packed__)); - -/* Transmit Status in CPU byteorder. */ -struct bcm43xx_xmitstatus { - u16 cookie; - u8 flags; - u8 cnt1:4, - cnt2:4; - u16 seq; - u16 unknown; //FIXME -}; - -#define BCM43xx_TXSTAT_FLAG_AMPDU 0x10 -#define BCM43xx_TXSTAT_FLAG_INTER 0x20 - -u8 bcm43xx_plcp_get_ratecode_cck(const u8 bitrate); -u8 bcm43xx_plcp_get_ratecode_ofdm(const u8 bitrate); - -int bcm43xx_rx(struct bcm43xx_private *bcm, - struct sk_buff *skb, - struct bcm43xx_rxhdr *rxhdr); - -#endif /* BCM43xx_XMIT_H_ */ -- cgit v1.2.3 From 7524d7d6de5d5d3f081de8cf5479819fad339661 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 4 Mar 2008 15:26:14 -0800 Subject: the scheduled ieee80211 softmac removal Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 8 - MAINTAINERS | 6 - include/net/ieee80211softmac.h | 373 ---------------- include/net/ieee80211softmac_wx.h | 99 ----- net/ieee80211/Kconfig | 1 - net/ieee80211/Makefile | 1 - net/ieee80211/softmac/Kconfig | 12 - net/ieee80211/softmac/Makefile | 9 - net/ieee80211/softmac/ieee80211softmac_assoc.c | 489 -------------------- net/ieee80211/softmac/ieee80211softmac_auth.c | 413 ----------------- net/ieee80211/softmac/ieee80211softmac_event.c | 189 -------- net/ieee80211/softmac/ieee80211softmac_io.c | 488 -------------------- net/ieee80211/softmac/ieee80211softmac_module.c | 568 ------------------------ net/ieee80211/softmac/ieee80211softmac_priv.h | 244 ---------- net/ieee80211/softmac/ieee80211softmac_scan.c | 254 ----------- net/ieee80211/softmac/ieee80211softmac_wx.c | 508 --------------------- 16 files changed, 3662 deletions(-) delete mode 100644 include/net/ieee80211softmac.h delete mode 100644 include/net/ieee80211softmac_wx.h delete mode 100644 net/ieee80211/softmac/Kconfig delete mode 100644 net/ieee80211/softmac/Makefile delete mode 100644 net/ieee80211/softmac/ieee80211softmac_assoc.c delete mode 100644 net/ieee80211/softmac/ieee80211softmac_auth.c delete mode 100644 net/ieee80211/softmac/ieee80211softmac_event.c delete mode 100644 net/ieee80211/softmac/ieee80211softmac_io.c delete mode 100644 net/ieee80211/softmac/ieee80211softmac_module.c delete mode 100644 net/ieee80211/softmac/ieee80211softmac_priv.h delete mode 100644 net/ieee80211/softmac/ieee80211softmac_scan.c delete mode 100644 net/ieee80211/softmac/ieee80211softmac_wx.c (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index dade1d14f5b2..2cf4d7ad7b0b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -230,14 +230,6 @@ Who: Jean Delvare --------------------------- -What: ieee80211 softmac wireless networking component -When: 2.6.26 (or after removal of bcm43xx and port of zd1211rw to mac80211) -Files: net/ieee80211/softmac -Why: No in-kernel drivers will depend on it any longer. -Who: John W. Linville - ---------------------------- - What: rc80211-simple rate control algorithm for mac80211 When: 2.6.26 Files: net/mac80211/rc80211-simple.c diff --git a/MAINTAINERS b/MAINTAINERS index 38b767611bbf..b9fc1f620f29 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3548,12 +3548,6 @@ M: mhoffman@lightlink.com L: lm-sensors@lm-sensors.org S: Maintained -SOFTMAC LAYER (IEEE 802.11) -P: Daniel Drake -M: dsd@gentoo.org -L: linux-wireless@vger.kernel.org -S: Obsolete - SOFTWARE RAID (Multiple Disks) SUPPORT P: Ingo Molnar M: mingo@redhat.com diff --git a/include/net/ieee80211softmac.h b/include/net/ieee80211softmac.h deleted file mode 100644 index 1ef6282fdded..000000000000 --- a/include/net/ieee80211softmac.h +++ /dev/null @@ -1,373 +0,0 @@ -/* - * ieee80211softmac.h - public interface to the softmac - * - * Copyright (c) 2005 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#ifndef IEEE80211SOFTMAC_H_ -#define IEEE80211SOFTMAC_H_ - -#include -#include -#include -#include -#include - -/* Once the API is considered more or less stable, - * this should be incremented on API incompatible changes. - */ -#define IEEE80211SOFTMAC_API 0 - -#define IEEE80211SOFTMAC_MAX_RATES_LEN 8 -#define IEEE80211SOFTMAC_MAX_EX_RATES_LEN 255 - -struct ieee80211softmac_ratesinfo { - u8 count; - u8 rates[IEEE80211SOFTMAC_MAX_RATES_LEN + IEEE80211SOFTMAC_MAX_EX_RATES_LEN]; -}; - -/* internal structures */ -struct ieee80211softmac_network; -struct ieee80211softmac_scaninfo; - -struct ieee80211softmac_essid { - u8 len; - char data[IW_ESSID_MAX_SIZE+1]; -}; - -struct ieee80211softmac_wpa { - char *IE; - int IElen; - int IEbuflen; -}; - -/* - * Information about association - */ -struct ieee80211softmac_assoc_info { - - struct mutex mutex; - - /* - * This is the requested ESSID. It is written - * only by the WX handlers. - * - */ - struct ieee80211softmac_essid req_essid; - /* - * the ESSID of the network we're currently - * associated (or trying) to. This is - * updated to the network's actual ESSID - * even if the requested ESSID was 'ANY' - */ - struct ieee80211softmac_essid associate_essid; - - /* BSSID we're trying to associate to */ - char bssid[ETH_ALEN]; - - /* some flags. - * static_essid is valid if the essid is constant, - * this is for use by the wx handlers only. - * - * associating is true, if the network has been - * auth'ed on and we are in the process of associating. - * - * bssvalid is true if we found a matching network - * and saved it's BSSID into the bssid above. - * - * bssfixed is used for SIOCSIWAP. - */ - u8 static_essid; - u8 short_preamble_available; - u8 associating; - u8 associated; - u8 assoc_wait; - u8 bssvalid; - u8 bssfixed; - - /* Scan retries remaining */ - int scan_retry; - - struct delayed_work work; - struct delayed_work timeout; -}; - -struct ieee80211softmac_bss_info { - /* Rates supported by the network */ - struct ieee80211softmac_ratesinfo supported_rates; - - /* This indicates whether frames can currently be transmitted with - * short preamble (only use this variable during TX at CCK rates) */ - u8 short_preamble:1; - - /* This indicates whether protection (e.g. self-CTS) should be used - * when transmitting with OFDM modulation */ - u8 use_protection:1; -}; - -enum { - IEEE80211SOFTMAC_AUTH_OPEN_REQUEST = 1, - IEEE80211SOFTMAC_AUTH_OPEN_RESPONSE = 2, -}; - -enum { - IEEE80211SOFTMAC_AUTH_SHARED_REQUEST = 1, - IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE = 2, - IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE = 3, - IEEE80211SOFTMAC_AUTH_SHARED_PASS = 4, -}; - -/* We should make these tunable - * AUTH_TIMEOUT seems really long, but that's what it is in BSD */ -#define IEEE80211SOFTMAC_AUTH_TIMEOUT (12 * HZ) -#define IEEE80211SOFTMAC_AUTH_RETRY_LIMIT 5 -#define IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT 3 - -struct ieee80211softmac_txrates { - /* The Bit-Rate to be used for multicast frames. */ - u8 mcast_rate; - - /* The Bit-Rate to be used for multicast management frames. */ - u8 mgt_mcast_rate; - - /* The Bit-Rate to be used for any other (normal) data packet. */ - u8 default_rate; - /* The Bit-Rate to be used for default fallback - * (If the device supports fallback and hardware-retry) - */ - u8 default_fallback; - - /* This is the rate that the user asked for */ - u8 user_rate; -}; - -/* Bits for txrates_change callback. */ -#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT (1 << 0) /* default_rate */ -#define IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK (1 << 1) /* default_fallback */ -#define IEEE80211SOFTMAC_TXRATECHG_MCAST (1 << 2) /* mcast_rate */ -#define IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST (1 << 3) /* mgt_mcast_rate */ - -#define IEEE80211SOFTMAC_BSSINFOCHG_RATES (1 << 0) /* supported_rates */ -#define IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE (1 << 1) /* short_preamble */ -#define IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION (1 << 2) /* use_protection */ - -struct ieee80211softmac_device { - /* 802.11 structure for data stuff */ - struct ieee80211_device *ieee; - struct net_device *dev; - - /* only valid if associated, then holds the Association ID */ - u16 association_id; - - /* the following methods are callbacks that the driver - * using this framework has to assign - */ - - /* always assign these */ - void (*set_bssid_filter)(struct net_device *dev, const u8 *bssid); - void (*set_channel)(struct net_device *dev, u8 channel); - - /* assign if you need it, informational only */ - void (*link_change)(struct net_device *dev); - - /* If the hardware can do scanning, assign _all_ three of these callbacks. - * When the scan finishes, call ieee80211softmac_scan_finished(). - */ - - /* when called, start_scan is guaranteed to not be called again - * until you call ieee80211softmac_scan_finished. - * Return 0 if scanning could start, error otherwise. - * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_start_scan */ - int (*start_scan)(struct net_device *dev); - /* this should block until after ieee80211softmac_scan_finished was called - * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_wait_for_scan */ - void (*wait_for_scan)(struct net_device *dev); - /* stop_scan aborts a scan, but is asynchronous. - * if you want to wait for it too, use wait_for_scan - * SOFTMAC AUTHORS: don't call this, use ieee80211softmac_stop_scan */ - void (*stop_scan)(struct net_device *dev); - - /* we'll need something about beacons here too, for AP or ad-hoc modes */ - - /* Transmission rates to be used by the driver. - * The SoftMAC figures out the best possible rates. - * The driver just needs to read them. - */ - struct ieee80211softmac_txrates txrates; - - /* If the driver needs to do stuff on TX rate changes, assign this - * callback. See IEEE80211SOFTMAC_TXRATECHG for change flags. */ - void (*txrates_change)(struct net_device *dev, - u32 changes); - - /* If the driver needs to do stuff when BSS properties change, assign - * this callback. see IEEE80211SOFTMAC_BSSINFOCHG for change flags. */ - void (*bssinfo_change)(struct net_device *dev, - u32 changes); - - /* private stuff follows */ - /* this lock protects this structure */ - spinlock_t lock; - - struct workqueue_struct *wq; - - u8 running; /* SoftMAC started? */ - u8 scanning; - - struct ieee80211softmac_scaninfo *scaninfo; - struct ieee80211softmac_assoc_info associnfo; - struct ieee80211softmac_bss_info bssinfo; - - struct list_head auth_queue; - struct list_head events; - - struct ieee80211softmac_ratesinfo ratesinfo; - int txrate_badness; - - /* WPA stuff */ - struct ieee80211softmac_wpa wpa; - - /* we need to keep a list of network structs we copied */ - struct list_head network_list; - - /* This must be the last item so that it points to the data - * allocated beyond this structure by alloc_ieee80211 */ - u8 priv[0]; -}; - -extern void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm); - -static inline void * ieee80211softmac_priv(struct net_device *dev) -{ - return ((struct ieee80211softmac_device *)ieee80211_priv(dev))->priv; -} - -extern struct net_device * alloc_ieee80211softmac(int sizeof_priv); -extern void free_ieee80211softmac(struct net_device *dev); - -/* Call this function if you detect a lost TX fragment. - * (If the device indicates failure of ACK RX, for example.) - * It is wise to call this function if you are able to detect lost packets, - * because it contributes to the TX Rates auto adjustment. - */ -extern void ieee80211softmac_fragment_lost(struct net_device *dev, - u16 wireless_sequence_number); -/* Call this function before _start to tell the softmac what rates - * the hw supports. The rates parameter is copied, so you can - * free it right after calling this function. - * Note that the rates need to be sorted. */ -extern void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates); - -/* Finds the highest rate which is: - * 1. Present in ri (optionally a basic rate) - * 2. Supported by the device - * 3. Less than or equal to the user-defined rate - */ -extern u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac, - struct ieee80211softmac_ratesinfo *ri, int basic_only); - -/* Helper function which advises you the rate at which a frame should be - * transmitted at. */ -static inline u8 ieee80211softmac_suggest_txrate(struct ieee80211softmac_device *mac, - int is_multicast, - int is_mgt) -{ - struct ieee80211softmac_txrates *txrates = &mac->txrates; - - if (!mac->associnfo.associated) - return txrates->mgt_mcast_rate; - - /* We are associated, sending unicast frame */ - if (!is_multicast) - return txrates->default_rate; - - /* We are associated, sending multicast frame */ - if (is_mgt) - return txrates->mgt_mcast_rate; - else - return txrates->mcast_rate; -} - -/* Helper function which advises you when it is safe to transmit with short - * preamble. - * You should only call this function when transmitting at CCK rates. */ -static inline int ieee80211softmac_short_preamble_ok(struct ieee80211softmac_device *mac, - int is_multicast, - int is_mgt) -{ - return (is_multicast && is_mgt) ? 0 : mac->bssinfo.short_preamble; -} - -/* Helper function which advises you whether protection (e.g. self-CTS) is - * needed. 1 = protection needed, 0 = no protection needed - * Only use this function when transmitting with OFDM modulation. */ -static inline int ieee80211softmac_protection_needed(struct ieee80211softmac_device *mac) -{ - return mac->bssinfo.use_protection; -} - -/* Start the SoftMAC. Call this after you initialized the device - * and it is ready to run. - */ -extern void ieee80211softmac_start(struct net_device *dev); -/* Stop the SoftMAC. Call this before you shutdown the device. */ -extern void ieee80211softmac_stop(struct net_device *dev); - -/* - * Event system - */ - -/* valid event types */ -#define IEEE80211SOFTMAC_EVENT_ANY -1 /*private use only*/ -#define IEEE80211SOFTMAC_EVENT_SCAN_FINISHED 0 -#define IEEE80211SOFTMAC_EVENT_ASSOCIATED 1 -#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED 2 -#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT 3 -#define IEEE80211SOFTMAC_EVENT_AUTHENTICATED 4 -#define IEEE80211SOFTMAC_EVENT_AUTH_FAILED 5 -#define IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT 6 -#define IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND 7 -#define IEEE80211SOFTMAC_EVENT_DISASSOCIATED 8 -/* keep this updated! */ -#define IEEE80211SOFTMAC_EVENT_LAST 8 -/* - * If you want to be notified of certain events, you can call - * ieee80211softmac_notify[_atomic] with - * - event set to one of the constants below - * - fun set to a function pointer of the appropriate type - * - context set to the context data you want passed - * The return value is 0, or an error. - */ -typedef void (*notify_function_ptr)(struct net_device *dev, int event_type, void *context); - -#define ieee80211softmac_notify(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_KERNEL); -#define ieee80211softmac_notify_atomic(dev, event, fun, context) ieee80211softmac_notify_gfp(dev, event, fun, context, GFP_ATOMIC); - -extern int ieee80211softmac_notify_gfp(struct net_device *dev, - int event, notify_function_ptr fun, void *context, gfp_t gfp_mask); - -/* To clear pending work (for ifconfig down, etc.) */ -extern void -ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm); - -#endif /* IEEE80211SOFTMAC_H_ */ diff --git a/include/net/ieee80211softmac_wx.h b/include/net/ieee80211softmac_wx.h deleted file mode 100644 index 4ee3ad57283f..000000000000 --- a/include/net/ieee80211softmac_wx.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * This file contains the prototypes for the wireless extension - * handlers that the softmac API provides. Include this file to - * use the wx handlers, you can assign these directly. - * - * Copyright (c) 2005 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#ifndef _IEEE80211SOFTMAC_WX_H -#define _IEEE80211SOFTMAC_WX_H - -#include -#include - -extern int -ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra); - -extern int -ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra); - -extern int -ieee80211softmac_wx_set_essid(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra); - -extern int -ieee80211softmac_wx_get_essid(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra); - -extern int -ieee80211softmac_wx_set_rate(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra); - -extern int -ieee80211softmac_wx_get_rate(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra); - -extern int -ieee80211softmac_wx_get_wap(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra); - -extern int -ieee80211softmac_wx_set_wap(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra); - -extern int -ieee80211softmac_wx_set_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra); - -extern int -ieee80211softmac_wx_get_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra); -extern int -ieee80211softmac_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra); -#endif /* _IEEE80211SOFTMAC_WX */ diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index bd501046c9c0..94ed7d3cd9da 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig @@ -71,4 +71,3 @@ config IEEE80211_CRYPT_TKIP This can be compiled as a module and it will be called "ieee80211_crypt_tkip". -source "net/ieee80211/softmac/Kconfig" diff --git a/net/ieee80211/Makefile b/net/ieee80211/Makefile index 796a7c76ee48..f988417121da 100644 --- a/net/ieee80211/Makefile +++ b/net/ieee80211/Makefile @@ -10,4 +10,3 @@ ieee80211-objs := \ ieee80211_wx.o \ ieee80211_geo.o -obj-$(CONFIG_IEEE80211_SOFTMAC) += softmac/ diff --git a/net/ieee80211/softmac/Kconfig b/net/ieee80211/softmac/Kconfig deleted file mode 100644 index 2811651cb134..000000000000 --- a/net/ieee80211/softmac/Kconfig +++ /dev/null @@ -1,12 +0,0 @@ -config IEEE80211_SOFTMAC - tristate "Software MAC add-on to the IEEE 802.11 networking stack" - depends on IEEE80211 && EXPERIMENTAL - select WIRELESS_EXT - select IEEE80211_CRYPT_WEP - ---help--- - This option enables the hardware independent software MAC addon - for the IEEE 802.11 networking stack. - -config IEEE80211_SOFTMAC_DEBUG - bool "Enable full debugging output" - depends on IEEE80211_SOFTMAC diff --git a/net/ieee80211/softmac/Makefile b/net/ieee80211/softmac/Makefile deleted file mode 100644 index bfcb391bb2c7..000000000000 --- a/net/ieee80211/softmac/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -obj-$(CONFIG_IEEE80211_SOFTMAC) += ieee80211softmac.o -ieee80211softmac-objs := \ - ieee80211softmac_io.o \ - ieee80211softmac_auth.o \ - ieee80211softmac_module.o \ - ieee80211softmac_scan.o \ - ieee80211softmac_wx.o \ - ieee80211softmac_assoc.o \ - ieee80211softmac_event.o diff --git a/net/ieee80211/softmac/ieee80211softmac_assoc.c b/net/ieee80211/softmac/ieee80211softmac_assoc.c deleted file mode 100644 index c4d122ddd72c..000000000000 --- a/net/ieee80211/softmac/ieee80211softmac_assoc.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * This file contains the softmac's association logic. - * - * Copyright (c) 2005, 2006 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#include "ieee80211softmac_priv.h" - -/* - * Overview - * - * Before you can associate, you have to authenticate. - * - */ - -/* Sends out an association request to the desired AP */ -static void -ieee80211softmac_assoc(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) -{ - unsigned long flags; - - /* Switch to correct channel for this network */ - mac->set_channel(mac->dev, net->channel); - - /* Send association request */ - ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_ASSOC_REQ, 0); - - dprintk(KERN_INFO PFX "sent association request!\n"); - - spin_lock_irqsave(&mac->lock, flags); - mac->associnfo.associated = 0; /* just to make sure */ - - /* Set a timer for timeout */ - /* FIXME: make timeout configurable */ - if (likely(mac->running)) - queue_delayed_work(mac->wq, &mac->associnfo.timeout, 5 * HZ); - spin_unlock_irqrestore(&mac->lock, flags); -} - -void -ieee80211softmac_assoc_timeout(struct work_struct *work) -{ - struct ieee80211softmac_device *mac = - container_of(work, struct ieee80211softmac_device, - associnfo.timeout.work); - struct ieee80211softmac_network *n; - - mutex_lock(&mac->associnfo.mutex); - /* we might race against ieee80211softmac_handle_assoc_response, - * so make sure only one of us does something */ - if (!mac->associnfo.associating) - goto out; - mac->associnfo.associating = 0; - mac->associnfo.bssvalid = 0; - mac->associnfo.associated = 0; - - n = ieee80211softmac_get_network_by_bssid_locked(mac, mac->associnfo.bssid); - - dprintk(KERN_INFO PFX "assoc request timed out!\n"); - ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_TIMEOUT, n); -out: - mutex_unlock(&mac->associnfo.mutex); -} - -void -ieee80211softmac_disassoc(struct ieee80211softmac_device *mac) -{ - unsigned long flags; - - spin_lock_irqsave(&mac->lock, flags); - if (mac->associnfo.associating) - cancel_delayed_work(&mac->associnfo.timeout); - - netif_carrier_off(mac->dev); - - mac->associnfo.associated = 0; - mac->associnfo.bssvalid = 0; - mac->associnfo.associating = 0; - ieee80211softmac_init_bss(mac); - ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_DISASSOCIATED, NULL); - spin_unlock_irqrestore(&mac->lock, flags); -} - -/* Sends out a disassociation request to the desired AP */ -void -ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason) -{ - struct ieee80211softmac_network *found; - - if (mac->associnfo.bssvalid && mac->associnfo.associated) { - found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); - if (found) - ieee80211softmac_send_mgt_frame(mac, found, IEEE80211_STYPE_DISASSOC, reason); - } - - ieee80211softmac_disassoc(mac); -} - -static inline int -we_support_all_basic_rates(struct ieee80211softmac_device *mac, u8 *from, u8 from_len) -{ - int idx; - u8 rate; - - for (idx = 0; idx < (from_len); idx++) { - rate = (from)[idx]; - if (!(rate & IEEE80211_BASIC_RATE_MASK)) - continue; - rate &= ~IEEE80211_BASIC_RATE_MASK; - if (!ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate)) - return 0; - } - return 1; -} - -static int -network_matches_request(struct ieee80211softmac_device *mac, struct ieee80211_network *net) -{ - /* we cannot associate to networks whose name we don't know */ - if (ieee80211_is_empty_essid(net->ssid, net->ssid_len)) - return 0; - /* do not associate to a network whose BSSBasicRateSet we cannot support */ - if (!we_support_all_basic_rates(mac, net->rates, net->rates_len)) - return 0; - /* do we really need to check the ex rates? */ - if (!we_support_all_basic_rates(mac, net->rates_ex, net->rates_ex_len)) - return 0; - - /* assume that users know what they're doing ... - * (note we don't let them select a net we're incompatible with) */ - if (mac->associnfo.bssfixed) { - return !memcmp(mac->associnfo.bssid, net->bssid, ETH_ALEN); - } - - /* if 'ANY' network requested, take any that doesn't have privacy enabled */ - if (mac->associnfo.req_essid.len == 0 - && !(net->capability & WLAN_CAPABILITY_PRIVACY)) - return 1; - if (net->ssid_len != mac->associnfo.req_essid.len) - return 0; - if (!memcmp(net->ssid, mac->associnfo.req_essid.data, mac->associnfo.req_essid.len)) - return 1; - return 0; -} - -static void -ieee80211softmac_assoc_notify_scan(struct net_device *dev, int event_type, void *context) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - ieee80211softmac_assoc_work(&mac->associnfo.work.work); -} - -static void -ieee80211softmac_assoc_notify_auth(struct net_device *dev, int event_type, void *context) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - - switch (event_type) { - case IEEE80211SOFTMAC_EVENT_AUTHENTICATED: - ieee80211softmac_assoc_work(&mac->associnfo.work.work); - break; - case IEEE80211SOFTMAC_EVENT_AUTH_FAILED: - case IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT: - ieee80211softmac_disassoc(mac); - break; - } -} - -/* This function is called to handle userspace requests (asynchronously) */ -void -ieee80211softmac_assoc_work(struct work_struct *work) -{ - struct ieee80211softmac_device *mac = - container_of(work, struct ieee80211softmac_device, - associnfo.work.work); - struct ieee80211softmac_network *found = NULL; - struct ieee80211_network *net = NULL, *best = NULL; - int bssvalid; - unsigned long flags; - - mutex_lock(&mac->associnfo.mutex); - - if (!mac->associnfo.associating) - goto out; - - /* ieee80211_disassoc might clear this */ - bssvalid = mac->associnfo.bssvalid; - - /* meh */ - if (mac->associnfo.associated) - ieee80211softmac_send_disassoc_req(mac, WLAN_REASON_DISASSOC_STA_HAS_LEFT); - - /* try to find the requested network in our list, if we found one already */ - if (bssvalid || mac->associnfo.bssfixed) - found = ieee80211softmac_get_network_by_bssid(mac, mac->associnfo.bssid); - - /* Search the ieee80211 networks for this network if we didn't find it by bssid, - * but only if we've scanned at least once (to get a better list of networks to - * select from). If we have not scanned before, the !found logic below will be - * invoked and will scan. */ - if (!found && (mac->associnfo.scan_retry < IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT)) - { - s8 rssi = -128; /* if I don't initialise, gcc emits an invalid warning - because it cannot follow the best pointer logic. */ - spin_lock_irqsave(&mac->ieee->lock, flags); - list_for_each_entry(net, &mac->ieee->network_list, list) { - /* we're supposed to find the network with - * the best signal here, as we're asked to join - * any network with a specific ESSID, and many - * different ones could have that. - * - * I'll for now just go with the reported rssi. - * - * We also should take into account the rateset - * here to find the best BSSID to try. - */ - if (network_matches_request(mac, net)) { - if (!best) { - best = net; - rssi = best->stats.rssi; - continue; - } - /* we already had a matching network, so - * compare their properties to get the - * better of the two ... (see above) - */ - if (rssi < net->stats.rssi) { - best = net; - rssi = best->stats.rssi; - } - } - } - /* if we unlock here, we might get interrupted and the `best' - * pointer could go stale */ - if (best) { - found = ieee80211softmac_create_network(mac, best); - /* if found is still NULL, then we got -ENOMEM somewhere */ - if (found) - ieee80211softmac_add_network(mac, found); - } - spin_unlock_irqrestore(&mac->ieee->lock, flags); - } - - if (!found) { - if (mac->associnfo.scan_retry > 0) { - mac->associnfo.scan_retry--; - - /* We know of no such network. Let's scan. - * NB: this also happens if we had no memory to copy the network info... - * Maybe we can hope to have more memory after scanning finishes ;) - */ - dprintk(KERN_INFO PFX "Associate: Scanning for networks first.\n"); - ieee80211softmac_notify(mac->dev, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, ieee80211softmac_assoc_notify_scan, NULL); - if (ieee80211softmac_start_scan(mac)) { - dprintk(KERN_INFO PFX "Associate: failed to initiate scan. Is device up?\n"); - } - goto out; - } else { - mac->associnfo.associating = 0; - mac->associnfo.associated = 0; - - dprintk(KERN_INFO PFX "Unable to find matching network after scan!\n"); - /* reset the retry counter for the next user request since we - * break out and don't reschedule ourselves after this point. */ - mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; - ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_NET_NOT_FOUND, NULL); - goto out; - } - } - - /* reset the retry counter for the next user request since we - * now found a net and will try to associate to it, but not - * schedule this function again. */ - mac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; - mac->associnfo.bssvalid = 1; - memcpy(mac->associnfo.bssid, found->bssid, ETH_ALEN); - /* copy the ESSID for displaying it */ - mac->associnfo.associate_essid.len = found->essid.len; - memcpy(mac->associnfo.associate_essid.data, found->essid.data, IW_ESSID_MAX_SIZE + 1); - - /* we found a network! authenticate (if necessary) and associate to it. */ - if (found->authenticating) { - dprintk(KERN_INFO PFX "Already requested authentication, waiting...\n"); - if(!mac->associnfo.assoc_wait) { - mac->associnfo.assoc_wait = 1; - ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); - } - goto out; - } - if (!found->authenticated && !found->authenticating) { - /* This relies on the fact that _auth_req only queues the work, - * otherwise adding the notification would be racy. */ - if (!ieee80211softmac_auth_req(mac, found)) { - if(!mac->associnfo.assoc_wait) { - dprintk(KERN_INFO PFX "Cannot associate without being authenticated, requested authentication\n"); - mac->associnfo.assoc_wait = 1; - ieee80211softmac_notify_internal(mac, IEEE80211SOFTMAC_EVENT_ANY, found, ieee80211softmac_assoc_notify_auth, NULL, GFP_KERNEL); - } - } else { - printkl(KERN_WARNING PFX "Not authenticated, but requesting authentication failed. Giving up to associate\n"); - mac->associnfo.assoc_wait = 0; - ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, found); - } - goto out; - } - /* finally! now we can start associating */ - mac->associnfo.assoc_wait = 0; - ieee80211softmac_assoc(mac, found); - -out: - mutex_unlock(&mac->associnfo.mutex); -} - -/* call this to do whatever is necessary when we're associated */ -static void -ieee80211softmac_associated(struct ieee80211softmac_device *mac, - struct ieee80211_assoc_response * resp, - struct ieee80211softmac_network *net) -{ - u16 cap = le16_to_cpu(resp->capability); - u8 erp_value = net->erp_value; - - mac->associnfo.associating = 0; - mac->bssinfo.supported_rates = net->supported_rates; - ieee80211softmac_recalc_txrates(mac); - - mac->associnfo.associated = 1; - - mac->associnfo.short_preamble_available = - (cap & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0; - ieee80211softmac_process_erp(mac, erp_value); - - if (mac->set_bssid_filter) - mac->set_bssid_filter(mac->dev, net->bssid); - memcpy(mac->ieee->bssid, net->bssid, ETH_ALEN); - netif_carrier_on(mac->dev); - - mac->association_id = le16_to_cpup(&resp->aid); -} - -/* received frame handling functions */ -int -ieee80211softmac_handle_assoc_response(struct net_device * dev, - struct ieee80211_assoc_response * resp, - struct ieee80211_network * _ieee80211_network) -{ - /* NOTE: the network parameter has to be mostly ignored by - * this code because it is the ieee80211's pointer - * to the struct, not ours (we made a copy) - */ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - u16 status = le16_to_cpup(&resp->status); - struct ieee80211softmac_network *network = NULL; - unsigned long flags; - DECLARE_MAC_BUF(mac2); - - if (unlikely(!mac->running)) - return -ENODEV; - - spin_lock_irqsave(&mac->lock, flags); - - if (!mac->associnfo.associating) { - /* we race against the timeout function, so make sure - * only one of us can do work */ - spin_unlock_irqrestore(&mac->lock, flags); - return 0; - } - network = ieee80211softmac_get_network_by_bssid_locked(mac, resp->header.addr3); - - /* someone sending us things without us knowing him? Ignore. */ - if (!network) { - dprintk(KERN_INFO PFX "Received unrequested assocation response from %s\n", - print_mac(mac2, resp->header.addr3)); - spin_unlock_irqrestore(&mac->lock, flags); - return 0; - } - - /* now that we know it was for us, we can cancel the timeout */ - cancel_delayed_work(&mac->associnfo.timeout); - - /* if the association response included an ERP IE, update our saved - * copy */ - if (_ieee80211_network->flags & NETWORK_HAS_ERP_VALUE) - network->erp_value = _ieee80211_network->erp_value; - - switch (status) { - case 0: - dprintk(KERN_INFO PFX "associated!\n"); - ieee80211softmac_associated(mac, resp, network); - ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATED, network); - break; - case WLAN_REASON_STA_REQ_ASSOC_WITHOUT_AUTH: - if (!network->auth_desynced_once) { - /* there seem to be a few rare cases where our view of - * the world is obscured, or buggy APs that don't DEAUTH - * us properly. So we handle that, but allow it only once. - */ - printkl(KERN_INFO PFX "We were not authenticated during association, retrying...\n"); - network->authenticated = 0; - /* we don't want to do this more than once ... */ - network->auth_desynced_once = 1; - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); - break; - } - default: - dprintk(KERN_INFO PFX "associating failed (reason: 0x%x)!\n", status); - mac->associnfo.associating = 0; - mac->associnfo.bssvalid = 0; - mac->associnfo.associated = 0; - ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_ASSOCIATE_FAILED, network); - } - - spin_unlock_irqrestore(&mac->lock, flags); - return 0; -} - -void -ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac) -{ - unsigned long flags; - - spin_lock_irqsave(&mac->lock, flags); - mac->associnfo.associating = 1; - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); - spin_unlock_irqrestore(&mac->lock, flags); -} - -int -ieee80211softmac_handle_disassoc(struct net_device * dev, - struct ieee80211_disassoc *disassoc) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - - if (unlikely(!mac->running)) - return -ENODEV; - - if (memcmp(disassoc->header.addr2, mac->associnfo.bssid, ETH_ALEN)) - return 0; - - if (memcmp(disassoc->header.addr1, mac->dev->dev_addr, ETH_ALEN)) - return 0; - - dprintk(KERN_INFO PFX "got disassoc frame\n"); - ieee80211softmac_disassoc(mac); - - ieee80211softmac_try_reassoc(mac); - - return 0; -} - -int -ieee80211softmac_handle_reassoc_req(struct net_device * dev, - struct ieee80211_reassoc_request * resp) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - struct ieee80211softmac_network *network; - - if (unlikely(!mac->running)) - return -ENODEV; - - network = ieee80211softmac_get_network_by_bssid(mac, resp->header.addr3); - if (!network) { - dprintkl(KERN_INFO PFX "reassoc request from unknown network\n"); - return 0; - } - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); - - return 0; -} diff --git a/net/ieee80211/softmac/ieee80211softmac_auth.c b/net/ieee80211/softmac/ieee80211softmac_auth.c deleted file mode 100644 index 1a96c2572578..000000000000 --- a/net/ieee80211/softmac/ieee80211softmac_auth.c +++ /dev/null @@ -1,413 +0,0 @@ -/* - * This file contains the softmac's authentication logic. - * - * Copyright (c) 2005, 2006 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#include "ieee80211softmac_priv.h" - -static void ieee80211softmac_auth_queue(struct work_struct *work); - -/* Queues an auth request to the desired AP */ -int -ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *net) -{ - struct ieee80211softmac_auth_queue_item *auth; - unsigned long flags; - DECLARE_MAC_BUF(mac2); - - if (net->authenticating || net->authenticated) - return 0; - net->authenticating = 1; - - /* Add the network if it's not already added */ - ieee80211softmac_add_network(mac, net); - - dprintk(KERN_NOTICE PFX "Queueing Authentication Request to %s\n", print_mac(mac2, net->bssid)); - /* Queue the auth request */ - auth = (struct ieee80211softmac_auth_queue_item *) - kmalloc(sizeof(struct ieee80211softmac_auth_queue_item), GFP_KERNEL); - if(auth == NULL) - return -ENOMEM; - - auth->net = net; - auth->mac = mac; - auth->retry = IEEE80211SOFTMAC_AUTH_RETRY_LIMIT; - auth->state = IEEE80211SOFTMAC_AUTH_OPEN_REQUEST; - INIT_DELAYED_WORK(&auth->work, ieee80211softmac_auth_queue); - - /* Lock (for list) */ - spin_lock_irqsave(&mac->lock, flags); - - /* add to list */ - list_add_tail(&auth->list, &mac->auth_queue); - queue_delayed_work(mac->wq, &auth->work, 0); - spin_unlock_irqrestore(&mac->lock, flags); - - return 0; -} - - -/* Sends an auth request to the desired AP and handles timeouts */ -static void -ieee80211softmac_auth_queue(struct work_struct *work) -{ - struct ieee80211softmac_device *mac; - struct ieee80211softmac_auth_queue_item *auth; - struct ieee80211softmac_network *net; - unsigned long flags; - DECLARE_MAC_BUF(mac2); - - auth = container_of(work, struct ieee80211softmac_auth_queue_item, - work.work); - net = auth->net; - mac = auth->mac; - - if(auth->retry > 0) { - /* Switch to correct channel for this network */ - mac->set_channel(mac->dev, net->channel); - - /* Lock and set flags */ - spin_lock_irqsave(&mac->lock, flags); - if (unlikely(!mac->running)) { - /* Prevent reschedule on workqueue flush */ - spin_unlock_irqrestore(&mac->lock, flags); - return; - } - net->authenticated = 0; - /* add a timeout call so we eventually give up waiting for an auth reply */ - queue_delayed_work(mac->wq, &auth->work, IEEE80211SOFTMAC_AUTH_TIMEOUT); - auth->retry--; - spin_unlock_irqrestore(&mac->lock, flags); - if (ieee80211softmac_send_mgt_frame(mac, auth->net, IEEE80211_STYPE_AUTH, auth->state)) - dprintk(KERN_NOTICE PFX "Sending Authentication Request to %s failed (this shouldn't happen, wait for the timeout).\n", - print_mac(mac2, net->bssid)); - else - dprintk(KERN_NOTICE PFX "Sent Authentication Request to %s.\n", print_mac(mac2, net->bssid)); - return; - } - - printkl(KERN_WARNING PFX "Authentication timed out with %s\n", print_mac(mac2, net->bssid)); - /* Remove this item from the queue */ - spin_lock_irqsave(&mac->lock, flags); - net->authenticating = 0; - ieee80211softmac_call_events_locked(mac, IEEE80211SOFTMAC_EVENT_AUTH_TIMEOUT, net); - cancel_delayed_work(&auth->work); /* just to make sure... */ - list_del(&auth->list); - spin_unlock_irqrestore(&mac->lock, flags); - /* Free it */ - kfree(auth); -} - -/* Sends a response to an auth challenge (for shared key auth). */ -static void -ieee80211softmac_auth_challenge_response(struct work_struct *work) -{ - struct ieee80211softmac_auth_queue_item *aq = - container_of(work, struct ieee80211softmac_auth_queue_item, - work.work); - - /* Send our response */ - ieee80211softmac_send_mgt_frame(aq->mac, aq->net, IEEE80211_STYPE_AUTH, aq->state); -} - -/* Handle the auth response from the AP - * This should be registered with ieee80211 as handle_auth - */ -int -ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth) -{ - - struct list_head *list_ptr; - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - struct ieee80211softmac_auth_queue_item *aq = NULL; - struct ieee80211softmac_network *net = NULL; - unsigned long flags; - u8 * data; - DECLARE_MAC_BUF(mac2); - - if (unlikely(!mac->running)) - return -ENODEV; - - /* Find correct auth queue item */ - spin_lock_irqsave(&mac->lock, flags); - list_for_each(list_ptr, &mac->auth_queue) { - aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list); - net = aq->net; - if (!memcmp(net->bssid, auth->header.addr2, ETH_ALEN)) - break; - else - aq = NULL; - } - spin_unlock_irqrestore(&mac->lock, flags); - - /* Make sure that we've got an auth queue item for this request */ - if(aq == NULL) - { - dprintkl(KERN_DEBUG PFX "Authentication response received from %s but no queue item exists.\n", print_mac(mac2, auth->header.addr2)); - /* Error #? */ - return -1; - } - - /* Check for out of order authentication */ - if(!net->authenticating) - { - dprintkl(KERN_DEBUG PFX "Authentication response received from %s but did not request authentication.\n",print_mac(mac2, auth->header.addr2)); - return -1; - } - - /* Parse the auth packet */ - switch(le16_to_cpu(auth->algorithm)) { - case WLAN_AUTH_OPEN: - /* Check the status code of the response */ - - switch(le16_to_cpu(auth->status)) { - case WLAN_STATUS_SUCCESS: - /* Update the status to Authenticated */ - spin_lock_irqsave(&mac->lock, flags); - net->authenticating = 0; - net->authenticated = 1; - spin_unlock_irqrestore(&mac->lock, flags); - - /* Send event */ - printkl(KERN_NOTICE PFX "Open Authentication completed with %s\n", print_mac(mac2, net->bssid)); - ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net); - break; - default: - /* Lock and reset flags */ - spin_lock_irqsave(&mac->lock, flags); - net->authenticated = 0; - net->authenticating = 0; - spin_unlock_irqrestore(&mac->lock, flags); - - printkl(KERN_NOTICE PFX "Open Authentication with %s failed, error code: %i\n", - print_mac(mac2, net->bssid), le16_to_cpup(&auth->status)); - /* Count the error? */ - break; - } - goto free_aq; - break; - case WLAN_AUTH_SHARED_KEY: - /* Figure out where we are in the process */ - switch(le16_to_cpu(auth->transaction)) { - case IEEE80211SOFTMAC_AUTH_SHARED_CHALLENGE: - /* Check to make sure we have a challenge IE */ - data = (u8 *)auth->info_element; - if (*data++ != MFIE_TYPE_CHALLENGE) { - printkl(KERN_NOTICE PFX "Shared Key Authentication failed due to a missing challenge.\n"); - break; - } - /* Save the challenge */ - spin_lock_irqsave(&mac->lock, flags); - net->challenge_len = *data++; - if (net->challenge_len > WLAN_AUTH_CHALLENGE_LEN) - net->challenge_len = WLAN_AUTH_CHALLENGE_LEN; - kfree(net->challenge); - net->challenge = kmemdup(data, net->challenge_len, - GFP_ATOMIC); - if (net->challenge == NULL) { - printkl(KERN_NOTICE PFX "Shared Key " - "Authentication failed due to " - "memory shortage.\n"); - spin_unlock_irqrestore(&mac->lock, flags); - break; - } - aq->state = IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE; - - /* We reuse the work struct from the auth request here. - * It is safe to do so as each one is per-request, and - * at this point (dealing with authentication response) - * we have obviously already sent the initial auth - * request. */ - cancel_delayed_work(&aq->work); - INIT_DELAYED_WORK(&aq->work, &ieee80211softmac_auth_challenge_response); - queue_delayed_work(mac->wq, &aq->work, 0); - spin_unlock_irqrestore(&mac->lock, flags); - return 0; - case IEEE80211SOFTMAC_AUTH_SHARED_PASS: - kfree(net->challenge); - net->challenge = NULL; - net->challenge_len = 0; - /* Check the status code of the response */ - switch(auth->status) { - case WLAN_STATUS_SUCCESS: - /* Update the status to Authenticated */ - spin_lock_irqsave(&mac->lock, flags); - net->authenticating = 0; - net->authenticated = 1; - spin_unlock_irqrestore(&mac->lock, flags); - printkl(KERN_NOTICE PFX "Shared Key Authentication completed with %s\n", - print_mac(mac2, net->bssid)); - ieee80211softmac_call_events(mac, IEEE80211SOFTMAC_EVENT_AUTHENTICATED, net); - break; - default: - printkl(KERN_NOTICE PFX "Shared Key Authentication with %s failed, error code: %i\n", - print_mac(mac2, net->bssid), le16_to_cpup(&auth->status)); - /* Lock and reset flags */ - spin_lock_irqsave(&mac->lock, flags); - net->authenticating = 0; - net->authenticated = 0; - spin_unlock_irqrestore(&mac->lock, flags); - /* Count the error? */ - break; - } - goto free_aq; - break; - default: - printkl(KERN_WARNING PFX "Unhandled Authentication Step: %i\n", auth->transaction); - break; - } - goto free_aq; - break; - default: - /* ERROR */ - goto free_aq; - break; - } - return 0; -free_aq: - /* Cancel the timeout */ - spin_lock_irqsave(&mac->lock, flags); - cancel_delayed_work(&aq->work); - /* Remove this item from the queue */ - list_del(&aq->list); - spin_unlock_irqrestore(&mac->lock, flags); - - /* Free it */ - kfree(aq); - return 0; -} - -/* - * Handle deauthorization - */ -static void -ieee80211softmac_deauth_from_net(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *net) -{ - struct ieee80211softmac_auth_queue_item *aq = NULL; - struct list_head *list_ptr; - unsigned long flags; - - /* deauthentication implies disassociation */ - ieee80211softmac_disassoc(mac); - - /* Lock and reset status flags */ - spin_lock_irqsave(&mac->lock, flags); - net->authenticating = 0; - net->authenticated = 0; - - /* Find correct auth queue item, if it exists */ - list_for_each(list_ptr, &mac->auth_queue) { - aq = list_entry(list_ptr, struct ieee80211softmac_auth_queue_item, list); - if (!memcmp(net->bssid, aq->net->bssid, ETH_ALEN)) - break; - else - aq = NULL; - } - - /* Cancel pending work */ - if(aq != NULL) - /* Not entirely safe? What about running work? */ - cancel_delayed_work(&aq->work); - - /* Free our network ref */ - ieee80211softmac_del_network_locked(mac, net); - if(net->challenge != NULL) - kfree(net->challenge); - kfree(net); - - /* can't transmit data right now... */ - netif_carrier_off(mac->dev); - spin_unlock_irqrestore(&mac->lock, flags); - - ieee80211softmac_try_reassoc(mac); -} - -/* - * Sends a deauth request to the desired AP - */ -int -ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *net, int reason) -{ - int ret; - - /* Make sure the network is authenticated */ - if (!net->authenticated) - { - dprintkl(KERN_DEBUG PFX "Can't send deauthentication packet, network is not authenticated.\n"); - /* Error okay? */ - return -EPERM; - } - - /* Send the de-auth packet */ - if((ret = ieee80211softmac_send_mgt_frame(mac, net, IEEE80211_STYPE_DEAUTH, reason))) - return ret; - - ieee80211softmac_deauth_from_net(mac, net); - return 0; -} - -/* - * This should be registered with ieee80211 as handle_deauth - */ -int -ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth) -{ - - struct ieee80211softmac_network *net = NULL; - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - DECLARE_MAC_BUF(mac2); - - if (unlikely(!mac->running)) - return -ENODEV; - - if (!deauth) { - dprintk("deauth without deauth packet. eek!\n"); - return 0; - } - - net = ieee80211softmac_get_network_by_bssid(mac, deauth->header.addr2); - - if (net == NULL) { - dprintkl(KERN_DEBUG PFX "Received deauthentication packet from %s, but that network is unknown.\n", - print_mac(mac2, deauth->header.addr2)); - return 0; - } - - /* Make sure the network is authenticated */ - if(!net->authenticated) - { - dprintkl(KERN_DEBUG PFX "Can't perform deauthentication, network is not authenticated.\n"); - /* Error okay? */ - return -EPERM; - } - - ieee80211softmac_deauth_from_net(mac, net); - - /* let's try to re-associate */ - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); - return 0; -} diff --git a/net/ieee80211/softmac/ieee80211softmac_event.c b/net/ieee80211/softmac/ieee80211softmac_event.c deleted file mode 100644 index 8cef05b60f16..000000000000 --- a/net/ieee80211/softmac/ieee80211softmac_event.c +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Event system - * Also see comments in public header file and longer explanation below. - * - * Copyright (c) 2005, 2006 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#include "ieee80211softmac_priv.h" - -/* - * Each event has associated to it - * - an event type (see constants in public header) - * - an event context (see below) - * - the function to be called - * - a context (extra parameter to call the function with) - * - and the softmac struct - * - * The event context is private and can only be used from - * within this module. Its meaning varies with the event - * type: - * SCAN_FINISHED, - * DISASSOCIATED: NULL - * ASSOCIATED, - * ASSOCIATE_FAILED, - * ASSOCIATE_TIMEOUT, - * AUTHENTICATED, - * AUTH_FAILED, - * AUTH_TIMEOUT: a pointer to the network struct - * ... - * Code within this module can use the event context to be only - * called when the event is true for that specific context - * as per above table. - * If the event context is NULL, then the notification is always called, - * regardless of the event context. The event context is not passed to - * the callback, it is assumed that the context suffices. - * - * You can also use the event context only by setting the event type - * to -1 (private use only), in which case you'll be notified - * whenever the event context matches. - */ - -static char *event_descriptions[IEEE80211SOFTMAC_EVENT_LAST+1] = { - NULL, /* scan finished */ - NULL, /* associated */ - "associating failed", - "associating timed out", - "authenticated", - "authenticating failed", - "authenticating timed out", - "associating failed because no suitable network was found", - NULL, /* disassociated */ -}; - - -static void -ieee80211softmac_notify_callback(struct work_struct *work) -{ - struct ieee80211softmac_event *pevent = - container_of(work, struct ieee80211softmac_event, work.work); - struct ieee80211softmac_event event = *pevent; - kfree(pevent); - - event.fun(event.mac->dev, event.event_type, event.context); -} - -int -ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac, - int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask) -{ - struct ieee80211softmac_event *eventptr; - unsigned long flags; - - if (event < -1 || event > IEEE80211SOFTMAC_EVENT_LAST) - return -ENOSYS; - - if (!fun) - return -EINVAL; - - eventptr = kmalloc(sizeof(struct ieee80211softmac_event), gfp_mask); - if (!eventptr) - return -ENOMEM; - - eventptr->event_type = event; - INIT_DELAYED_WORK(&eventptr->work, ieee80211softmac_notify_callback); - eventptr->fun = fun; - eventptr->context = context; - eventptr->mac = mac; - eventptr->event_context = event_context; - - spin_lock_irqsave(&mac->lock, flags); - list_add(&eventptr->list, &mac->events); - spin_unlock_irqrestore(&mac->lock, flags); - - return 0; -} - -int -ieee80211softmac_notify_gfp(struct net_device *dev, - int event, notify_function_ptr fun, void *context, gfp_t gfp_mask) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - - if (event < 0 || event > IEEE80211SOFTMAC_EVENT_LAST) - return -ENOSYS; - - return ieee80211softmac_notify_internal(mac, event, NULL, fun, context, gfp_mask); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_notify_gfp); - -/* private -- calling all callbacks that were specified */ -void -ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_ctx) -{ - struct ieee80211softmac_event *eventptr, *tmp; - struct ieee80211softmac_network *network; - - if (event >= 0) { - union iwreq_data wrqu; - int we_event; - char *msg = NULL; - - memset(&wrqu, '\0', sizeof (union iwreq_data)); - - switch(event) { - case IEEE80211SOFTMAC_EVENT_ASSOCIATED: - network = (struct ieee80211softmac_network *)event_ctx; - memcpy(wrqu.ap_addr.sa_data, &network->bssid[0], ETH_ALEN); - /* fall through */ - case IEEE80211SOFTMAC_EVENT_DISASSOCIATED: - wrqu.ap_addr.sa_family = ARPHRD_ETHER; - we_event = SIOCGIWAP; - break; - case IEEE80211SOFTMAC_EVENT_SCAN_FINISHED: - we_event = SIOCGIWSCAN; - break; - default: - msg = event_descriptions[event]; - if (!msg) - msg = "SOFTMAC EVENT BUG"; - wrqu.data.length = strlen(msg); - we_event = IWEVCUSTOM; - break; - } - wireless_send_event(mac->dev, we_event, &wrqu, msg); - } - - if (!list_empty(&mac->events)) - list_for_each_entry_safe(eventptr, tmp, &mac->events, list) { - if ((eventptr->event_type == event || eventptr->event_type == -1) - && (eventptr->event_context == NULL || eventptr->event_context == event_ctx)) { - list_del(&eventptr->list); - /* User may have subscribed to ANY event, so - * we tell them which event triggered it. */ - eventptr->event_type = event; - queue_delayed_work(mac->wq, &eventptr->work, 0); - } - } -} - -void -ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_ctx) -{ - unsigned long flags; - - spin_lock_irqsave(&mac->lock, flags); - ieee80211softmac_call_events_locked(mac, event, event_ctx); - - spin_unlock_irqrestore(&mac->lock, flags); -} diff --git a/net/ieee80211/softmac/ieee80211softmac_io.c b/net/ieee80211/softmac/ieee80211softmac_io.c deleted file mode 100644 index 73b4b13fbd8f..000000000000 --- a/net/ieee80211/softmac/ieee80211softmac_io.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Some parts based on code from net80211 - * Copyright (c) 2001 Atsushi Onoe - * Copyright (c) 2002-2005 Sam Leffler, Errno Consulting - * 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. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * 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. - * - */ - -#include "ieee80211softmac_priv.h" - -/* Helper functions for inserting data into the frames */ - -/* - * Adds an ESSID element to the frame - * - */ -static u8 * -ieee80211softmac_add_essid(u8 *dst, struct ieee80211softmac_essid *essid) -{ - if (essid) { - *dst++ = MFIE_TYPE_SSID; - *dst++ = essid->len; - memcpy(dst, essid->data, essid->len); - return dst+essid->len; - } else { - *dst++ = MFIE_TYPE_SSID; - *dst++ = 0; - return dst; - } -} - -/* Adds Supported Rates and if required Extended Rates Information Element - * to the frame, ASSUMES WE HAVE A SORTED LIST OF RATES */ -static u8 * -ieee80211softmac_frame_add_rates(u8 *dst, const struct ieee80211softmac_ratesinfo *r) -{ - int cck_len, ofdm_len; - *dst++ = MFIE_TYPE_RATES; - - for(cck_len=0; ieee80211_is_cck_rate(r->rates[cck_len]) && (cck_len < r->count);cck_len++); - - if(cck_len > IEEE80211SOFTMAC_MAX_RATES_LEN) - cck_len = IEEE80211SOFTMAC_MAX_RATES_LEN; - *dst++ = cck_len; - memcpy(dst, r->rates, cck_len); - dst += cck_len; - - if(cck_len < r->count){ - for (ofdm_len=0; ieee80211_is_ofdm_rate(r->rates[ofdm_len + cck_len]) && (ofdm_len + cck_len < r->count); ofdm_len++); - if (ofdm_len > 0) { - if (ofdm_len > IEEE80211SOFTMAC_MAX_EX_RATES_LEN) - ofdm_len = IEEE80211SOFTMAC_MAX_EX_RATES_LEN; - *dst++ = MFIE_TYPE_RATES_EX; - *dst++ = ofdm_len; - memcpy(dst, r->rates + cck_len, ofdm_len); - dst += ofdm_len; - } - } - return dst; -} - -/* Allocate a management frame */ -static u8 * -ieee80211softmac_alloc_mgt(u32 size) -{ - u8 * data; - - /* Add the header and FCS to the size */ - size = size + IEEE80211_3ADDR_LEN; - if(size > IEEE80211_DATA_LEN) - return NULL; - /* Allocate the frame */ - data = kzalloc(size, GFP_ATOMIC); - return data; -} - -/* - * Add a 2 Address Header - */ -static void -ieee80211softmac_hdr_2addr(struct ieee80211softmac_device *mac, - struct ieee80211_hdr_2addr *header, u32 type, u8 *dest) -{ - /* Fill in the frame control flags */ - header->frame_ctl = cpu_to_le16(type); - /* Control packets always have WEP turned off */ - if(type > IEEE80211_STYPE_CFENDACK && type < IEEE80211_STYPE_PSPOLL) - header->frame_ctl |= mac->ieee->sec.level ? cpu_to_le16(IEEE80211_FCTL_PROTECTED) : 0; - - /* Fill in the duration */ - header->duration_id = 0; - /* FIXME: How do I find this? - * calculate. But most drivers just fill in 0 (except if it's a station id of course) */ - - /* Fill in the Destination Address */ - if(dest == NULL) - memset(header->addr1, 0xFF, ETH_ALEN); - else - memcpy(header->addr1, dest, ETH_ALEN); - /* Fill in the Source Address */ - memcpy(header->addr2, mac->ieee->dev->dev_addr, ETH_ALEN); - -} - - -/* Add a 3 Address Header */ -static void -ieee80211softmac_hdr_3addr(struct ieee80211softmac_device *mac, - struct ieee80211_hdr_3addr *header, u32 type, u8 *dest, u8 *bssid) -{ - /* This is common with 2addr, so use that instead */ - ieee80211softmac_hdr_2addr(mac, (struct ieee80211_hdr_2addr *)header, type, dest); - - /* Fill in the BSS ID */ - if(bssid == NULL) - memset(header->addr3, 0xFF, ETH_ALEN); - else - memcpy(header->addr3, bssid, ETH_ALEN); - - /* Fill in the sequence # */ - /* FIXME: I need to add this to the softmac struct - * shouldn't the sequence number be in ieee80211? */ -} - -static __le16 -ieee80211softmac_capabilities(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *net) -{ - __le16 capability = 0; - - /* ESS and IBSS bits are set according to the current mode */ - switch (mac->ieee->iw_mode) { - case IW_MODE_INFRA: - capability = cpu_to_le16(WLAN_CAPABILITY_ESS); - break; - case IW_MODE_ADHOC: - capability = cpu_to_le16(WLAN_CAPABILITY_IBSS); - break; - case IW_MODE_AUTO: - capability = cpu_to_le16(net->capabilities & - (WLAN_CAPABILITY_ESS|WLAN_CAPABILITY_IBSS)); - break; - default: - /* bleh. we don't ever go to these modes */ - printk(KERN_ERR PFX "invalid iw_mode!\n"); - break; - } - - /* CF Pollable / CF Poll Request */ - /* Needs to be implemented, for now, the 0's == not supported */ - - /* Privacy Bit */ - capability |= mac->ieee->sec.level ? - cpu_to_le16(WLAN_CAPABILITY_PRIVACY) : 0; - - /* Short Preamble */ - /* Always supported: we probably won't ever be powering devices which - * dont support this... */ - capability |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE); - - /* PBCC */ - /* Not widely used */ - - /* Channel Agility */ - /* Not widely used */ - - /* Short Slot */ - /* Will be implemented later */ - - /* DSSS-OFDM */ - /* Not widely used */ - - return capability; -} - -/***************************************************************************** - * Create Management packets - *****************************************************************************/ - -/* Creates an association request packet */ -static u32 -ieee80211softmac_assoc_req(struct ieee80211_assoc_request **pkt, - struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) -{ - u8 *data; - (*pkt) = (struct ieee80211_assoc_request *)ieee80211softmac_alloc_mgt( - 2 + /* Capability Info */ - 2 + /* Listen Interval */ - /* SSID IE */ - 1 + 1 + IW_ESSID_MAX_SIZE + - /* Rates IE */ - 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + - /* Extended Rates IE */ - 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN + - /* WPA IE if present */ - mac->wpa.IElen - /* Other IE's? Optional? - * Yeah, probably need an extra IE parameter -- lots of vendors like to - * fill in their own IEs */ - ); - if (unlikely((*pkt) == NULL)) - return 0; - ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_ASSOC_REQ, net->bssid, net->bssid); - - /* Fill in the capabilities */ - (*pkt)->capability = ieee80211softmac_capabilities(mac, net); - - /* Fill in Listen Interval (?) */ - (*pkt)->listen_interval = cpu_to_le16(10); - - data = (u8 *)(*pkt)->info_element; - /* Add SSID */ - data = ieee80211softmac_add_essid(data, &net->essid); - /* Add Rates */ - data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); - /* Add WPA IE */ - if (mac->wpa.IElen && mac->wpa.IE) { - memcpy(data, mac->wpa.IE, mac->wpa.IElen); - data += mac->wpa.IElen; - } - /* Return the number of used bytes */ - return (data - (u8*)(*pkt)); -} - -/* Create a reassociation request packet */ -static u32 -ieee80211softmac_reassoc_req(struct ieee80211_reassoc_request **pkt, - struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) -{ - u8 *data; - (*pkt) = (struct ieee80211_reassoc_request *)ieee80211softmac_alloc_mgt( - 2 + /* Capability Info */ - 2 + /* Listen Interval */ - ETH_ALEN + /* AP MAC */ - /* SSID IE */ - 1 + 1 + IW_ESSID_MAX_SIZE + - /* Rates IE */ - 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + - /* Extended Rates IE */ - 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN - /* Other IE's? */ - ); - if (unlikely((*pkt) == NULL)) - return 0; - ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_REASSOC_REQ, net->bssid, net->bssid); - - /* Fill in the capabilities */ - (*pkt)->capability = ieee80211softmac_capabilities(mac, net); - - /* Fill in Listen Interval (?) */ - (*pkt)->listen_interval = cpu_to_le16(10); - /* Fill in the current AP MAC */ - memcpy((*pkt)->current_ap, mac->ieee->bssid, ETH_ALEN); - - data = (u8 *)(*pkt)->info_element; - /* Add SSID */ - data = ieee80211softmac_add_essid(data, &net->essid); - /* Add Rates */ - data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); - /* Return packet size */ - return (data - (u8 *)(*pkt)); -} - -/* Create an authentication packet */ -static u32 -ieee80211softmac_auth(struct ieee80211_auth **pkt, - struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, - u16 transaction, u16 status, int *encrypt_mpdu) -{ - u8 *data; - int auth_mode = mac->ieee->sec.auth_mode; - int is_shared_response = (auth_mode == WLAN_AUTH_SHARED_KEY - && transaction == IEEE80211SOFTMAC_AUTH_SHARED_RESPONSE); - - /* Allocate Packet */ - (*pkt) = (struct ieee80211_auth *)ieee80211softmac_alloc_mgt( - 2 + /* Auth Algorithm */ - 2 + /* Auth Transaction Seq */ - 2 + /* Status Code */ - /* Challenge Text IE */ - (is_shared_response ? 1 + 1 + net->challenge_len : 0) - ); - if (unlikely((*pkt) == NULL)) - return 0; - ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_AUTH, net->bssid, net->bssid); - - /* Algorithm */ - (*pkt)->algorithm = cpu_to_le16(auth_mode); - /* Transaction */ - (*pkt)->transaction = cpu_to_le16(transaction); - /* Status */ - (*pkt)->status = cpu_to_le16(status); - - data = (u8 *)(*pkt)->info_element; - /* Challenge Text */ - if (is_shared_response) { - *data = MFIE_TYPE_CHALLENGE; - data++; - - /* Copy the challenge in */ - *data = net->challenge_len; - data++; - memcpy(data, net->challenge, net->challenge_len); - data += net->challenge_len; - - /* Make sure this frame gets encrypted with the shared key */ - *encrypt_mpdu = 1; - } else - *encrypt_mpdu = 0; - - /* Return the packet size */ - return (data - (u8 *)(*pkt)); -} - -/* Create a disassocation or deauthentication packet */ -static u32 -ieee80211softmac_disassoc_deauth(struct ieee80211_disassoc **pkt, - struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, - u16 type, u16 reason) -{ - /* Allocate Packet */ - (*pkt) = (struct ieee80211_disassoc *)ieee80211softmac_alloc_mgt(2); - if (unlikely((*pkt) == NULL)) - return 0; - ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), type, net->bssid, net->bssid); - /* Reason */ - (*pkt)->reason = cpu_to_le16(reason); - /* Return the packet size */ - return (2 + IEEE80211_3ADDR_LEN); -} - -/* Create a probe request packet */ -static u32 -ieee80211softmac_probe_req(struct ieee80211_probe_request **pkt, - struct ieee80211softmac_device *mac, struct ieee80211softmac_essid *essid) -{ - u8 *data; - /* Allocate Packet */ - (*pkt) = (struct ieee80211_probe_request *)ieee80211softmac_alloc_mgt( - /* SSID of requested network */ - 1 + 1 + IW_ESSID_MAX_SIZE + - /* Rates IE */ - 1 + 1 + IEEE80211SOFTMAC_MAX_RATES_LEN + - /* Extended Rates IE */ - 1 + 1 + IEEE80211SOFTMAC_MAX_EX_RATES_LEN - ); - if (unlikely((*pkt) == NULL)) - return 0; - ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_REQ, NULL, NULL); - - data = (u8 *)(*pkt)->info_element; - /* Add ESSID (can be NULL) */ - data = ieee80211softmac_add_essid(data, essid); - /* Add Rates */ - data = ieee80211softmac_frame_add_rates(data, &mac->ratesinfo); - /* Return packet size */ - return (data - (u8 *)(*pkt)); -} - -/* Create a probe response packet */ -/* FIXME: Not complete */ -static u32 -ieee80211softmac_probe_resp(struct ieee80211_probe_response **pkt, - struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net) -{ - u8 *data; - /* Allocate Packet */ - (*pkt) = (struct ieee80211_probe_response *)ieee80211softmac_alloc_mgt( - 8 + /* Timestamp */ - 2 + /* Beacon Interval */ - 2 + /* Capability Info */ - /* SSID IE */ - 1 + 1 + IW_ESSID_MAX_SIZE + - 7 + /* FH Parameter Set */ - 2 + /* DS Parameter Set */ - 8 + /* CF Parameter Set */ - 4 /* IBSS Parameter Set */ - ); - if (unlikely((*pkt) == NULL)) - return 0; - ieee80211softmac_hdr_3addr(mac, &((*pkt)->header), IEEE80211_STYPE_PROBE_RESP, net->bssid, net->bssid); - data = (u8 *)(*pkt)->info_element; - - /* Return the packet size */ - return (data - (u8 *)(*pkt)); -} - - -/* Sends a manangement packet - * FIXME: document the use of the arg parameter - * for _AUTH: (transaction #) | (status << 16) - */ -int -ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, - void *ptrarg, u32 type, u32 arg) -{ - void *pkt = NULL; - u32 pkt_size = 0; - int encrypt_mpdu = 0; - - switch(type) { - case IEEE80211_STYPE_ASSOC_REQ: - pkt_size = ieee80211softmac_assoc_req((struct ieee80211_assoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); - break; - case IEEE80211_STYPE_REASSOC_REQ: - pkt_size = ieee80211softmac_reassoc_req((struct ieee80211_reassoc_request **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); - break; - case IEEE80211_STYPE_AUTH: - pkt_size = ieee80211softmac_auth((struct ieee80211_auth **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, (u16)(arg & 0xFFFF), (u16) (arg >> 16), &encrypt_mpdu); - break; - case IEEE80211_STYPE_DISASSOC: - case IEEE80211_STYPE_DEAUTH: - pkt_size = ieee80211softmac_disassoc_deauth((struct ieee80211_disassoc **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg, type, (u16)(arg & 0xFFFF)); - break; - case IEEE80211_STYPE_PROBE_REQ: - pkt_size = ieee80211softmac_probe_req((struct ieee80211_probe_request **)(&pkt), mac, (struct ieee80211softmac_essid *)ptrarg); - break; - case IEEE80211_STYPE_PROBE_RESP: - pkt_size = ieee80211softmac_probe_resp((struct ieee80211_probe_response **)(&pkt), mac, (struct ieee80211softmac_network *)ptrarg); - break; - default: - printkl(KERN_DEBUG PFX "Unsupported Management Frame type: %i\n", type); - return -EINVAL; - }; - - if(pkt_size == 0 || pkt == NULL) { - printkl(KERN_DEBUG PFX "Error, packet is nonexistant or 0 length\n"); - return -ENOMEM; - } - - /* Send the packet to the ieee80211 layer for tx */ - /* we defined softmac->mgmt_xmit for this. Should we keep it - * as it is (that means we'd need to wrap this into a txb), - * modify the prototype (so it matches this function), - * or get rid of it alltogether? - * Does this work for you now? - */ - ieee80211_tx_frame(mac->ieee, (struct ieee80211_hdr *)pkt, - IEEE80211_3ADDR_LEN, pkt_size, encrypt_mpdu); - - kfree(pkt); - return 0; -} - -/* Beacon handling */ -int ieee80211softmac_handle_beacon(struct net_device *dev, - struct ieee80211_beacon *beacon, - struct ieee80211_network *network) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - - /* This might race, but we don't really care and it's not worth - * adding heavyweight locking in this fastpath. - */ - if (mac->associnfo.associated) { - if (memcmp(network->bssid, mac->associnfo.bssid, ETH_ALEN) == 0) - ieee80211softmac_process_erp(mac, network->erp_value); - } - - return 0; -} - diff --git a/net/ieee80211/softmac/ieee80211softmac_module.c b/net/ieee80211/softmac/ieee80211softmac_module.c deleted file mode 100644 index 07505ca859af..000000000000 --- a/net/ieee80211/softmac/ieee80211softmac_module.c +++ /dev/null @@ -1,568 +0,0 @@ -/* - * Contains some basic softmac functions along with module registration code etc. - * - * Copyright (c) 2005, 2006 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#include "ieee80211softmac_priv.h" -#include -#include - -struct net_device *alloc_ieee80211softmac(int sizeof_priv) -{ - struct ieee80211softmac_device *softmac; - struct net_device *dev; - - dev = alloc_ieee80211(sizeof(*softmac) + sizeof_priv); - if (!dev) - return NULL; - softmac = ieee80211_priv(dev); - softmac->wq = create_freezeable_workqueue("softmac"); - if (!softmac->wq) { - free_ieee80211(dev); - return NULL; - } - - softmac->dev = dev; - softmac->ieee = netdev_priv(dev); - spin_lock_init(&softmac->lock); - - softmac->ieee->handle_auth = ieee80211softmac_auth_resp; - softmac->ieee->handle_deauth = ieee80211softmac_deauth_resp; - softmac->ieee->handle_assoc_response = ieee80211softmac_handle_assoc_response; - softmac->ieee->handle_reassoc_request = ieee80211softmac_handle_reassoc_req; - softmac->ieee->handle_disassoc = ieee80211softmac_handle_disassoc; - softmac->ieee->handle_beacon = ieee80211softmac_handle_beacon; - softmac->scaninfo = NULL; - - softmac->associnfo.scan_retry = IEEE80211SOFTMAC_ASSOC_SCAN_RETRY_LIMIT; - - /* TODO: initialise all the other callbacks in the ieee struct - * (once they're written) - */ - - INIT_LIST_HEAD(&softmac->auth_queue); - INIT_LIST_HEAD(&softmac->network_list); - INIT_LIST_HEAD(&softmac->events); - - mutex_init(&softmac->associnfo.mutex); - INIT_DELAYED_WORK(&softmac->associnfo.work, ieee80211softmac_assoc_work); - INIT_DELAYED_WORK(&softmac->associnfo.timeout, ieee80211softmac_assoc_timeout); - softmac->start_scan = ieee80211softmac_start_scan_implementation; - softmac->wait_for_scan = ieee80211softmac_wait_for_scan_implementation; - softmac->stop_scan = ieee80211softmac_stop_scan_implementation; - - /* to start with, we can't send anything ... */ - netif_carrier_off(dev); - - return dev; -} -EXPORT_SYMBOL_GPL(alloc_ieee80211softmac); - -/* Clears the pending work queue items, stops all scans, etc. */ -void -ieee80211softmac_clear_pending_work(struct ieee80211softmac_device *sm) -{ - unsigned long flags; - struct ieee80211softmac_event *eventptr, *eventtmp; - struct ieee80211softmac_auth_queue_item *authptr, *authtmp; - struct ieee80211softmac_network *netptr, *nettmp; - - ieee80211softmac_stop_scan(sm); - ieee80211softmac_wait_for_scan(sm); - - spin_lock_irqsave(&sm->lock, flags); - sm->running = 0; - - /* Free all pending assoc work items */ - cancel_delayed_work(&sm->associnfo.work); - - /* Free all pending scan work items */ - if(sm->scaninfo != NULL) - cancel_delayed_work(&sm->scaninfo->softmac_scan); - - /* Free all pending auth work items */ - list_for_each_entry(authptr, &sm->auth_queue, list) - cancel_delayed_work(&authptr->work); - - /* delete all pending event calls and work items */ - list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) - cancel_delayed_work(&eventptr->work); - - spin_unlock_irqrestore(&sm->lock, flags); - flush_workqueue(sm->wq); - - /* now we should be save and no longer need locking... */ - spin_lock_irqsave(&sm->lock, flags); - /* Free all pending auth work items */ - list_for_each_entry_safe(authptr, authtmp, &sm->auth_queue, list) { - list_del(&authptr->list); - kfree(authptr); - } - - /* delete all pending event calls and work items */ - list_for_each_entry_safe(eventptr, eventtmp, &sm->events, list) { - list_del(&eventptr->list); - kfree(eventptr); - } - - /* Free all networks */ - list_for_each_entry_safe(netptr, nettmp, &sm->network_list, list) { - ieee80211softmac_del_network_locked(sm, netptr); - if(netptr->challenge != NULL) - kfree(netptr->challenge); - kfree(netptr); - } - - spin_unlock_irqrestore(&sm->lock, flags); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_clear_pending_work); - -void free_ieee80211softmac(struct net_device *dev) -{ - struct ieee80211softmac_device *sm = ieee80211_priv(dev); - ieee80211softmac_clear_pending_work(sm); - kfree(sm->scaninfo); - kfree(sm->wpa.IE); - destroy_workqueue(sm->wq); - free_ieee80211(dev); -} -EXPORT_SYMBOL_GPL(free_ieee80211softmac); - -static void ieee80211softmac_start_check_rates(struct ieee80211softmac_device *mac) -{ - struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; - /* I took out the sorting check, we're seperating by modulation now. */ - if (ri->count) - return; - /* otherwise assume we hav'em all! */ - if (mac->ieee->modulation & IEEE80211_CCK_MODULATION) { - ri->rates[ri->count++] = IEEE80211_CCK_RATE_1MB; - ri->rates[ri->count++] = IEEE80211_CCK_RATE_2MB; - ri->rates[ri->count++] = IEEE80211_CCK_RATE_5MB; - ri->rates[ri->count++] = IEEE80211_CCK_RATE_11MB; - } - if (mac->ieee->modulation & IEEE80211_OFDM_MODULATION) { - ri->rates[ri->count++] = IEEE80211_OFDM_RATE_6MB; - ri->rates[ri->count++] = IEEE80211_OFDM_RATE_9MB; - ri->rates[ri->count++] = IEEE80211_OFDM_RATE_12MB; - ri->rates[ri->count++] = IEEE80211_OFDM_RATE_18MB; - ri->rates[ri->count++] = IEEE80211_OFDM_RATE_24MB; - ri->rates[ri->count++] = IEEE80211_OFDM_RATE_36MB; - ri->rates[ri->count++] = IEEE80211_OFDM_RATE_48MB; - ri->rates[ri->count++] = IEEE80211_OFDM_RATE_54MB; - } -} - -int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate) -{ - int search; - u8 search_rate; - - for (search = 0; search < ri->count; search++) { - search_rate = ri->rates[search]; - search_rate &= ~IEEE80211_BASIC_RATE_MASK; - if (rate == search_rate) - return 1; - } - - return 0; -} - -u8 ieee80211softmac_highest_supported_rate(struct ieee80211softmac_device *mac, - struct ieee80211softmac_ratesinfo *ri, int basic_only) -{ - u8 user_rate = mac->txrates.user_rate; - int i; - - if (ri->count == 0) - return IEEE80211_CCK_RATE_1MB; - - for (i = ri->count - 1; i >= 0; i--) { - u8 rate = ri->rates[i]; - if (basic_only && !(rate & IEEE80211_BASIC_RATE_MASK)) - continue; - rate &= ~IEEE80211_BASIC_RATE_MASK; - if (rate > user_rate) - continue; - if (ieee80211softmac_ratesinfo_rate_supported(&mac->ratesinfo, rate)) - return rate; - } - - /* If we haven't found a suitable rate by now, just trust the user */ - return user_rate; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_highest_supported_rate); - -void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac, - u8 erp_value) -{ - int use_protection; - int short_preamble; - u32 changes = 0; - - /* Barker preamble mode */ - short_preamble = ((erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0 - && mac->associnfo.short_preamble_available) ? 1 : 0; - - /* Protection needed? */ - use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; - - if (mac->bssinfo.short_preamble != short_preamble) { - changes |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE; - mac->bssinfo.short_preamble = short_preamble; - } - - if (mac->bssinfo.use_protection != use_protection) { - changes |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION; - mac->bssinfo.use_protection = use_protection; - } - - if (mac->bssinfo_change && changes) - mac->bssinfo_change(mac->dev, changes); -} - -void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac) -{ - struct ieee80211softmac_txrates *txrates = &mac->txrates; - u32 change = 0; - - change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; - txrates->default_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 0); - - change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; - txrates->default_fallback = lower_rate(mac, txrates->default_rate); - - change |= IEEE80211SOFTMAC_TXRATECHG_MCAST; - txrates->mcast_rate = ieee80211softmac_highest_supported_rate(mac, &mac->bssinfo.supported_rates, 1); - - if (mac->txrates_change) - mac->txrates_change(mac->dev, change); - -} - -void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac) -{ - struct ieee80211_device *ieee = mac->ieee; - u32 change = 0; - struct ieee80211softmac_txrates *txrates = &mac->txrates; - struct ieee80211softmac_bss_info *bssinfo = &mac->bssinfo; - - /* TODO: We need some kind of state machine to lower the default rates - * if we loose too many packets. - */ - /* Change the default txrate to the highest possible value. - * The txrate machine will lower it, if it is too high. - */ - if (ieee->modulation & IEEE80211_OFDM_MODULATION) - txrates->user_rate = IEEE80211_OFDM_RATE_24MB; - else - txrates->user_rate = IEEE80211_CCK_RATE_11MB; - - txrates->default_rate = IEEE80211_CCK_RATE_1MB; - change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; - - txrates->default_fallback = IEEE80211_CCK_RATE_1MB; - change |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; - - txrates->mcast_rate = IEEE80211_CCK_RATE_1MB; - change |= IEEE80211SOFTMAC_TXRATECHG_MCAST; - - txrates->mgt_mcast_rate = IEEE80211_CCK_RATE_1MB; - change |= IEEE80211SOFTMAC_TXRATECHG_MGT_MCAST; - - if (mac->txrates_change) - mac->txrates_change(mac->dev, change); - - change = 0; - - bssinfo->supported_rates.count = 0; - memset(bssinfo->supported_rates.rates, 0, - sizeof(bssinfo->supported_rates.rates)); - change |= IEEE80211SOFTMAC_BSSINFOCHG_RATES; - - bssinfo->short_preamble = 0; - change |= IEEE80211SOFTMAC_BSSINFOCHG_SHORT_PREAMBLE; - - bssinfo->use_protection = 0; - change |= IEEE80211SOFTMAC_BSSINFOCHG_PROTECTION; - - if (mac->bssinfo_change) - mac->bssinfo_change(mac->dev, change); - - mac->running = 1; -} - -void ieee80211softmac_start(struct net_device *dev) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - - ieee80211softmac_start_check_rates(mac); - ieee80211softmac_init_bss(mac); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_start); - -void ieee80211softmac_stop(struct net_device *dev) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - - ieee80211softmac_clear_pending_work(mac); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_stop); - -void ieee80211softmac_set_rates(struct net_device *dev, u8 count, u8 *rates) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&mac->lock, flags); - memcpy(mac->ratesinfo.rates, rates, count); - mac->ratesinfo.count = count; - spin_unlock_irqrestore(&mac->lock, flags); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_set_rates); - -static u8 raise_rate(struct ieee80211softmac_device *mac, u8 rate) -{ - int i; - struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; - - for (i=0; icount-1; i++) { - if (ri->rates[i] == rate) - return ri->rates[i+1]; - } - /* I guess we can't go any higher... */ - return ri->rates[ri->count]; -} - -u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta) -{ - int i; - struct ieee80211softmac_ratesinfo *ri = &mac->ratesinfo; - - for (i=delta; icount; i++) { - if (ri->rates[i] == rate) - return ri->rates[i-delta]; - } - /* I guess we can't go any lower... */ - return ri->rates[0]; -} - -static void ieee80211softmac_add_txrates_badness(struct ieee80211softmac_device *mac, - int amount) -{ - u8 default_rate = mac->txrates.default_rate; - u8 default_fallback = mac->txrates.default_fallback; - u32 changes = 0; - - //TODO: This is highly experimental code. - // Maybe the dynamic rate selection does not work - // and it has to be removed again. - -printk("badness %d\n", mac->txrate_badness); - mac->txrate_badness += amount; - if (mac->txrate_badness <= -1000) { - /* Very small badness. Try a faster bitrate. */ - default_rate = raise_rate(mac, default_rate); - changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; - default_fallback = get_fallback_rate(mac, default_rate); - changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; - mac->txrate_badness = 0; -printk("Bitrate raised to %u\n", default_rate); - } else if (mac->txrate_badness >= 10000) { - /* Very high badness. Try a slower bitrate. */ - default_rate = lower_rate(mac, default_rate); - changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT; - default_fallback = get_fallback_rate(mac, default_rate); - changes |= IEEE80211SOFTMAC_TXRATECHG_DEFAULT_FBACK; - mac->txrate_badness = 0; -printk("Bitrate lowered to %u\n", default_rate); - } - - mac->txrates.default_rate = default_rate; - mac->txrates.default_fallback = default_fallback; - - if (changes && mac->txrates_change) - mac->txrates_change(mac->dev, changes); -} - -void ieee80211softmac_fragment_lost(struct net_device *dev, - u16 wl_seq) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&mac->lock, flags); - ieee80211softmac_add_txrates_badness(mac, 1000); - //TODO - - spin_unlock_irqrestore(&mac->lock, flags); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_fragment_lost); - -static int rate_cmp(const void *a_, const void *b_) { - u8 *a, *b; - a = (u8*)a_; - b = (u8*)b_; - return ((*a & ~IEEE80211_BASIC_RATE_MASK) - (*b & ~IEEE80211_BASIC_RATE_MASK)); -} - -/* Allocate a softmac network struct and fill it from a network */ -struct ieee80211softmac_network * -ieee80211softmac_create_network(struct ieee80211softmac_device *mac, - struct ieee80211_network *net) -{ - struct ieee80211softmac_network *softnet; - softnet = kzalloc(sizeof(struct ieee80211softmac_network), GFP_ATOMIC); - if(softnet == NULL) - return NULL; - memcpy(softnet->bssid, net->bssid, ETH_ALEN); - softnet->channel = net->channel; - softnet->essid.len = net->ssid_len; - memcpy(softnet->essid.data, net->ssid, softnet->essid.len); - - /* copy rates over */ - softnet->supported_rates.count = net->rates_len; - memcpy(&softnet->supported_rates.rates[0], net->rates, net->rates_len); - memcpy(&softnet->supported_rates.rates[softnet->supported_rates.count], net->rates_ex, net->rates_ex_len); - softnet->supported_rates.count += net->rates_ex_len; - sort(softnet->supported_rates.rates, softnet->supported_rates.count, sizeof(softnet->supported_rates.rates[0]), rate_cmp, NULL); - - /* we save the ERP value because it is needed at association time, and - * many AP's do not include an ERP IE in the association response. */ - softnet->erp_value = net->erp_value; - - softnet->capabilities = net->capability; - return softnet; -} - - -/* Add a network to the list, while locked */ -void -ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *add_net) -{ - struct ieee80211softmac_network *softmac_net; - - list_for_each_entry(softmac_net, &mac->network_list, list) { - if(!memcmp(softmac_net->bssid, add_net->bssid, ETH_ALEN)) - return; - } - list_add(&(add_net->list), &mac->network_list); -} - -/* Add a network to the list, with locking */ -void -ieee80211softmac_add_network(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *add_net) -{ - unsigned long flags; - spin_lock_irqsave(&mac->lock, flags); - ieee80211softmac_add_network_locked(mac, add_net); - spin_unlock_irqrestore(&mac->lock, flags); -} - - -/* Delete a network from the list, while locked*/ -void -ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *del_net) -{ - list_del(&(del_net->list)); -} - -/* Delete a network from the list with locking */ -void -ieee80211softmac_del_network(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *del_net) -{ - unsigned long flags; - spin_lock_irqsave(&mac->lock, flags); - ieee80211softmac_del_network_locked(mac, del_net); - spin_unlock_irqrestore(&mac->lock, flags); -} - -/* Get a network from the list by MAC while locked */ -struct ieee80211softmac_network * -ieee80211softmac_get_network_by_bssid_locked(struct ieee80211softmac_device *mac, - u8 *bssid) -{ - struct ieee80211softmac_network *softmac_net; - - list_for_each_entry(softmac_net, &mac->network_list, list) { - if(!memcmp(softmac_net->bssid, bssid, ETH_ALEN)) - return softmac_net; - } - return NULL; -} - -/* Get a network from the list by BSSID with locking */ -struct ieee80211softmac_network * -ieee80211softmac_get_network_by_bssid(struct ieee80211softmac_device *mac, - u8 *bssid) -{ - unsigned long flags; - struct ieee80211softmac_network *softmac_net; - - spin_lock_irqsave(&mac->lock, flags); - softmac_net = ieee80211softmac_get_network_by_bssid_locked(mac, bssid); - spin_unlock_irqrestore(&mac->lock, flags); - return softmac_net; -} - -/* Get a network from the list by ESSID while locked */ -struct ieee80211softmac_network * -ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac, - struct ieee80211softmac_essid *essid) -{ - struct ieee80211softmac_network *softmac_net; - - list_for_each_entry(softmac_net, &mac->network_list, list) { - if (softmac_net->essid.len == essid->len && - !memcmp(softmac_net->essid.data, essid->data, essid->len)) - return softmac_net; - } - return NULL; -} - -/* Get a network from the list by ESSID with locking */ -struct ieee80211softmac_network * -ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac, - struct ieee80211softmac_essid *essid) -{ - unsigned long flags; - struct ieee80211softmac_network *softmac_net = NULL; - - spin_lock_irqsave(&mac->lock, flags); - softmac_net = ieee80211softmac_get_network_by_essid_locked(mac, essid); - spin_unlock_irqrestore(&mac->lock, flags); - return softmac_net; -} - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Johannes Berg"); -MODULE_AUTHOR("Joseph Jezak"); -MODULE_AUTHOR("Larry Finger"); -MODULE_AUTHOR("Danny van Dyk"); -MODULE_AUTHOR("Michael Buesch"); -MODULE_DESCRIPTION("802.11 software MAC"); diff --git a/net/ieee80211/softmac/ieee80211softmac_priv.h b/net/ieee80211/softmac/ieee80211softmac_priv.h deleted file mode 100644 index f9232c8f6bdc..000000000000 --- a/net/ieee80211/softmac/ieee80211softmac_priv.h +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Internal softmac API definitions. - * - * Copyright (c) 2005, 2006 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#ifndef IEEE80211SOFTMAC_PRIV_H_ -#define IEEE80211SOFTMAC_PRIV_H_ - -#include -#include -#include -#include - - -#define PFX "SoftMAC: " - -#ifdef assert -# undef assert -#endif -#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG -#define assert(expr) \ - do { \ - if (unlikely(!(expr))) { \ - printkl(KERN_ERR PFX "ASSERTION FAILED (%s) at: %s:%d:%s()\n", #expr, \ - __FILE__, __LINE__, __func__); \ - } \ - } while (0) -#else -#define assert(expr) do {} while (0) -#endif - -/* rate limited printk(). */ -#ifdef printkl -# undef printkl -#endif -#define printkl(f, x...) do { if (printk_ratelimit()) printk(f ,##x); } while (0) -/* rate limited printk() for debugging */ -#ifdef dprintkl -# undef dprintkl -#endif -#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG -# define dprintkl printkl -#else -# define dprintkl(f, x...) do { /* nothing */ } while (0) -#endif - -/* debugging printk() */ -#ifdef dprintk -# undef dprintk -#endif -#ifdef CONFIG_IEEE80211_SOFTMAC_DEBUG -# define dprintk(f, x...) do { printk(f ,##x); } while (0) -#else -# define dprintk(f, x...) do { /* nothing */ } while (0) -#endif - -/* private definitions and prototypes */ - -/*** prototypes from _scan.c */ -void ieee80211softmac_scan(struct work_struct *work); -/* for internal use if scanning is needed */ -int ieee80211softmac_start_scan(struct ieee80211softmac_device *mac); -void ieee80211softmac_stop_scan(struct ieee80211softmac_device *mac); -void ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *mac); - -/* for use by _module.c to assign to the callbacks */ -int ieee80211softmac_start_scan_implementation(struct net_device *dev); -void ieee80211softmac_stop_scan_implementation(struct net_device *dev); -void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev); - -/*** Network prototypes from _module.c */ -struct ieee80211softmac_network * ieee80211softmac_create_network( - struct ieee80211softmac_device *mac, struct ieee80211_network *net); -void ieee80211softmac_add_network_locked(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *net); -void ieee80211softmac_add_network(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *net); -void ieee80211softmac_del_network_locked(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *net); -void ieee80211softmac_del_network(struct ieee80211softmac_device *mac, - struct ieee80211softmac_network *net); -struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid_locked( - struct ieee80211softmac_device *mac, u8 *ea); -struct ieee80211softmac_network * ieee80211softmac_get_network_by_bssid( - struct ieee80211softmac_device *mac, u8 *ea); -struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid_locked( - struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len); -struct ieee80211softmac_network * ieee80211softmac_get_network_by_ssid( - struct ieee80211softmac_device *mac, u8 *ssid, u8 ssid_len); -struct ieee80211softmac_network * -ieee80211softmac_get_network_by_essid_locked(struct ieee80211softmac_device *mac, - struct ieee80211softmac_essid *essid); -struct ieee80211softmac_network * -ieee80211softmac_get_network_by_essid(struct ieee80211softmac_device *mac, - struct ieee80211softmac_essid *essid); - -/* Rates related */ -void ieee80211softmac_process_erp(struct ieee80211softmac_device *mac, - u8 erp_value); -int ieee80211softmac_ratesinfo_rate_supported(struct ieee80211softmac_ratesinfo *ri, u8 rate); -u8 ieee80211softmac_lower_rate_delta(struct ieee80211softmac_device *mac, u8 rate, int delta); -void ieee80211softmac_init_bss(struct ieee80211softmac_device *mac); -void ieee80211softmac_recalc_txrates(struct ieee80211softmac_device *mac); -static inline u8 lower_rate(struct ieee80211softmac_device *mac, u8 rate) { - return ieee80211softmac_lower_rate_delta(mac, rate, 1); -} - -static inline u8 get_fallback_rate(struct ieee80211softmac_device *mac, u8 rate) -{ - return ieee80211softmac_lower_rate_delta(mac, rate, 2); -} - - -/*** prototypes from _io.c */ -int ieee80211softmac_send_mgt_frame(struct ieee80211softmac_device *mac, - void* ptrarg, u32 type, u32 arg); -int ieee80211softmac_handle_beacon(struct net_device *dev, - struct ieee80211_beacon *beacon, - struct ieee80211_network *network); - -/*** prototypes from _auth.c */ -/* do these have to go into the public header? */ -int ieee80211softmac_auth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net); -int ieee80211softmac_deauth_req(struct ieee80211softmac_device *mac, struct ieee80211softmac_network *net, int reason); - -/* for use by _module.c to assign to the callbacks */ -int ieee80211softmac_auth_resp(struct net_device *dev, struct ieee80211_auth *auth); -int ieee80211softmac_deauth_resp(struct net_device *dev, struct ieee80211_deauth *deauth); - -/*** prototypes from _assoc.c */ -void ieee80211softmac_assoc_work(struct work_struct *work); -int ieee80211softmac_handle_assoc_response(struct net_device * dev, - struct ieee80211_assoc_response * resp, - struct ieee80211_network * network); -int ieee80211softmac_handle_disassoc(struct net_device * dev, - struct ieee80211_disassoc * disassoc); -int ieee80211softmac_handle_reassoc_req(struct net_device * dev, - struct ieee80211_reassoc_request * reassoc); -void ieee80211softmac_assoc_timeout(struct work_struct *work); -void ieee80211softmac_send_disassoc_req(struct ieee80211softmac_device *mac, u16 reason); -void ieee80211softmac_disassoc(struct ieee80211softmac_device *mac); - -/* some helper functions */ -static inline int ieee80211softmac_scan_handlers_check_self(struct ieee80211softmac_device *sm) -{ - return (sm->start_scan == ieee80211softmac_start_scan_implementation) && - (sm->stop_scan == ieee80211softmac_stop_scan_implementation) && - (sm->wait_for_scan == ieee80211softmac_wait_for_scan_implementation); -} - -static inline int ieee80211softmac_scan_sanity_check(struct ieee80211softmac_device *sm) -{ - return ((sm->start_scan != ieee80211softmac_start_scan_implementation) && - (sm->stop_scan != ieee80211softmac_stop_scan_implementation) && - (sm->wait_for_scan != ieee80211softmac_wait_for_scan_implementation) - ) || ieee80211softmac_scan_handlers_check_self(sm); -} - -#define IEEE80211SOFTMAC_PROBE_DELAY HZ/50 -#define IEEE80211SOFTMAC_WORKQUEUE_NAME_LEN (17 + IFNAMSIZ) - -struct ieee80211softmac_network { - struct list_head list; /* List */ - /* Network information copied from ieee80211_network */ - u8 bssid[ETH_ALEN]; - u8 channel; - struct ieee80211softmac_essid essid; - - struct ieee80211softmac_ratesinfo supported_rates; - - /* SoftMAC specific */ - u16 authenticating:1, /* Status Flags */ - authenticated:1, - auth_desynced_once:1; - - u8 erp_value; /* Saved ERP value */ - u16 capabilities; /* Capabilities bitfield */ - u8 challenge_len; /* Auth Challenge length */ - char *challenge; /* Challenge Text */ -}; - -/* structure used to keep track of networks we're auth'ing to */ -struct ieee80211softmac_auth_queue_item { - struct list_head list; /* List head */ - struct ieee80211softmac_network *net; /* Network to auth */ - struct ieee80211softmac_device *mac; /* SoftMAC device */ - u8 retry; /* Retry limit */ - u8 state; /* Auth State */ - struct delayed_work work; /* Work queue */ -}; - -/* scanning information */ -struct ieee80211softmac_scaninfo { - u8 current_channel_idx, - number_channels; - struct ieee80211_channel *channels; - u8 started:1, - stop:1; - u8 skip_flags; - struct completion finished; - struct delayed_work softmac_scan; - struct ieee80211softmac_device *mac; -}; - -/* private event struct */ -struct ieee80211softmac_event { - struct list_head list; - int event_type; - void *event_context; - struct delayed_work work; - notify_function_ptr fun; - void *context; - struct ieee80211softmac_device *mac; -}; - -void ieee80211softmac_call_events(struct ieee80211softmac_device *mac, int event, void *event_context); -void ieee80211softmac_call_events_locked(struct ieee80211softmac_device *mac, int event, void *event_context); -int ieee80211softmac_notify_internal(struct ieee80211softmac_device *mac, - int event, void *event_context, notify_function_ptr fun, void *context, gfp_t gfp_mask); - -void ieee80211softmac_try_reassoc(struct ieee80211softmac_device *mac); - -#endif /* IEEE80211SOFTMAC_PRIV_H_ */ diff --git a/net/ieee80211/softmac/ieee80211softmac_scan.c b/net/ieee80211/softmac/ieee80211softmac_scan.c deleted file mode 100644 index bfab8d7db88f..000000000000 --- a/net/ieee80211/softmac/ieee80211softmac_scan.c +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Scanning routines. - * - * These are not exported because they're assigned to the function pointers. - * - * Copyright (c) 2005, 2006 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#include -#include "ieee80211softmac_priv.h" - -/* internal, use to trigger scanning if needed. - * Returns -EBUSY if already scanning, - * result of start_scan otherwise */ -int -ieee80211softmac_start_scan(struct ieee80211softmac_device *sm) -{ - unsigned long flags; - int ret; - - spin_lock_irqsave(&sm->lock, flags); - if (sm->scanning) - { - spin_unlock_irqrestore(&sm->lock, flags); - return -EINPROGRESS; - } - sm->scanning = 1; - spin_unlock_irqrestore(&sm->lock, flags); - - ret = sm->start_scan(sm->dev); - if (ret) { - spin_lock_irqsave(&sm->lock, flags); - sm->scanning = 0; - spin_unlock_irqrestore(&sm->lock, flags); - } - return ret; -} - -void -ieee80211softmac_stop_scan(struct ieee80211softmac_device *sm) -{ - unsigned long flags; - - spin_lock_irqsave(&sm->lock, flags); - - if (!sm->scanning) { - spin_unlock_irqrestore(&sm->lock, flags); - return; - } - - spin_unlock_irqrestore(&sm->lock, flags); - sm->stop_scan(sm->dev); -} - -void -ieee80211softmac_wait_for_scan(struct ieee80211softmac_device *sm) -{ - unsigned long flags; - - spin_lock_irqsave(&sm->lock, flags); - - if (!sm->scanning) { - spin_unlock_irqrestore(&sm->lock, flags); - return; - } - - spin_unlock_irqrestore(&sm->lock, flags); - sm->wait_for_scan(sm->dev); -} - - -/* internal scanning implementation follows */ -void ieee80211softmac_scan(struct work_struct *work) -{ - int invalid_channel; - u8 current_channel_idx; - struct ieee80211softmac_scaninfo *si = - container_of(work, struct ieee80211softmac_scaninfo, - softmac_scan.work); - struct ieee80211softmac_device *sm = si->mac; - unsigned long flags; - - while (!(si->stop) && (si->current_channel_idx < si->number_channels)) { - current_channel_idx = si->current_channel_idx; - si->current_channel_idx++; /* go to the next channel */ - - invalid_channel = (si->skip_flags & si->channels[current_channel_idx].flags); - - if (!invalid_channel) { - sm->set_channel(sm->dev, si->channels[current_channel_idx].channel); - // FIXME make this user configurable (active/passive) - if(ieee80211softmac_send_mgt_frame(sm, NULL, IEEE80211_STYPE_PROBE_REQ, 0)) - printkl(KERN_DEBUG PFX "Sending Probe Request Failed\n"); - - /* also send directed management frame for the network we're looking for */ - // TODO: is this if correct, or should we do this only if scanning from assoc request? - if (sm->associnfo.req_essid.len) - ieee80211softmac_send_mgt_frame(sm, &sm->associnfo.req_essid, IEEE80211_STYPE_PROBE_REQ, 0); - - spin_lock_irqsave(&sm->lock, flags); - if (unlikely(!sm->running)) { - /* Prevent reschedule on workqueue flush */ - spin_unlock_irqrestore(&sm->lock, flags); - break; - } - queue_delayed_work(sm->wq, &si->softmac_scan, IEEE80211SOFTMAC_PROBE_DELAY); - spin_unlock_irqrestore(&sm->lock, flags); - return; - } else { - dprintk(PFX "Not probing Channel %d (not allowed here)\n", si->channels[current_channel_idx].channel); - } - } - - spin_lock_irqsave(&sm->lock, flags); - cancel_delayed_work(&si->softmac_scan); - si->started = 0; - spin_unlock_irqrestore(&sm->lock, flags); - - dprintk(PFX "Scanning finished: scanned %d channels starting with channel %d\n", - sm->scaninfo->number_channels, sm->scaninfo->channels[0].channel); - ieee80211softmac_scan_finished(sm); - complete_all(&sm->scaninfo->finished); -} - -static inline struct ieee80211softmac_scaninfo *allocate_scaninfo(struct ieee80211softmac_device *mac) -{ - /* ugh. can we call this without having the spinlock held? */ - struct ieee80211softmac_scaninfo *info = kmalloc(sizeof(struct ieee80211softmac_scaninfo), GFP_ATOMIC); - if (unlikely(!info)) - return NULL; - INIT_DELAYED_WORK(&info->softmac_scan, ieee80211softmac_scan); - info->mac = mac; - init_completion(&info->finished); - return info; -} - -int ieee80211softmac_start_scan_implementation(struct net_device *dev) -{ - struct ieee80211softmac_device *sm = ieee80211_priv(dev); - unsigned long flags; - - if (!(dev->flags & IFF_UP)) - return -ENODEV; - - assert(ieee80211softmac_scan_handlers_check_self(sm)); - if (!ieee80211softmac_scan_handlers_check_self(sm)) - return -EINVAL; - - spin_lock_irqsave(&sm->lock, flags); - /* it looks like we need to hold the lock here - * to make sure we don't allocate two of these... */ - if (unlikely(!sm->scaninfo)) - sm->scaninfo = allocate_scaninfo(sm); - if (unlikely(!sm->scaninfo)) { - spin_unlock_irqrestore(&sm->lock, flags); - return -ENOMEM; - } - - sm->scaninfo->skip_flags = IEEE80211_CH_INVALID; - if (0 /* not scanning in IEEE802.11b */)//TODO - sm->scaninfo->skip_flags |= IEEE80211_CH_B_ONLY; - if (0 /* IEEE802.11a */) {//TODO - sm->scaninfo->channels = sm->ieee->geo.a; - sm->scaninfo->number_channels = sm->ieee->geo.a_channels; - } else { - sm->scaninfo->channels = sm->ieee->geo.bg; - sm->scaninfo->number_channels = sm->ieee->geo.bg_channels; - } - sm->scaninfo->current_channel_idx = 0; - sm->scaninfo->started = 1; - sm->scaninfo->stop = 0; - INIT_COMPLETION(sm->scaninfo->finished); - queue_delayed_work(sm->wq, &sm->scaninfo->softmac_scan, 0); - spin_unlock_irqrestore(&sm->lock, flags); - return 0; -} - -void ieee80211softmac_stop_scan_implementation(struct net_device *dev) -{ - struct ieee80211softmac_device *sm = ieee80211_priv(dev); - unsigned long flags; - - assert(ieee80211softmac_scan_handlers_check_self(sm)); - if (!ieee80211softmac_scan_handlers_check_self(sm)) - return; - - spin_lock_irqsave(&sm->lock, flags); - assert(sm->scaninfo != NULL); - if (sm->scaninfo) { - if (sm->scaninfo->started) - sm->scaninfo->stop = 1; - else - complete_all(&sm->scaninfo->finished); - } - spin_unlock_irqrestore(&sm->lock, flags); -} - -void ieee80211softmac_wait_for_scan_implementation(struct net_device *dev) -{ - struct ieee80211softmac_device *sm = ieee80211_priv(dev); - unsigned long flags; - - assert(ieee80211softmac_scan_handlers_check_self(sm)); - if (!ieee80211softmac_scan_handlers_check_self(sm)) - return; - - spin_lock_irqsave(&sm->lock, flags); - if (!sm->scaninfo->started) { - spin_unlock_irqrestore(&sm->lock, flags); - return; - } - spin_unlock_irqrestore(&sm->lock, flags); - wait_for_completion(&sm->scaninfo->finished); -} - -/* this is what drivers (that do scanning) call when they're done */ -void ieee80211softmac_scan_finished(struct ieee80211softmac_device *sm) -{ - unsigned long flags; - - spin_lock_irqsave(&sm->lock, flags); - sm->scanning = 0; - spin_unlock_irqrestore(&sm->lock, flags); - - if (sm->associnfo.bssvalid) { - struct ieee80211softmac_network *net; - - net = ieee80211softmac_get_network_by_bssid(sm, sm->associnfo.bssid); - if (net) - sm->set_channel(sm->dev, net->channel); - } - ieee80211softmac_call_events(sm, IEEE80211SOFTMAC_EVENT_SCAN_FINISHED, NULL); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_scan_finished); diff --git a/net/ieee80211/softmac/ieee80211softmac_wx.c b/net/ieee80211/softmac/ieee80211softmac_wx.c deleted file mode 100644 index e01b59aedc54..000000000000 --- a/net/ieee80211/softmac/ieee80211softmac_wx.c +++ /dev/null @@ -1,508 +0,0 @@ -/* - * This file contains our _wx handlers. Make sure you EXPORT_SYMBOL_GPL them - * - * Copyright (c) 2005, 2006 Johannes Berg - * Joseph Jezak - * Larry Finger - * Danny van Dyk - * Michael Buesch - * - * 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 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 St, Fifth Floor, Boston, MA 02110-1301 USA - * - * The full GNU General Public License is included in this distribution in the - * file called COPYING. - */ - -#include "ieee80211softmac_priv.h" - -#include -/* for is_broadcast_ether_addr and is_zero_ether_addr */ -#include - -int -ieee80211softmac_wx_trigger_scan(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); - return ieee80211softmac_start_scan(sm); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_trigger_scan); - - -/* if we're still scanning, return -EAGAIN so that userspace tools - * can get the complete scan results, otherwise return 0. */ -int -ieee80211softmac_wx_get_scan_results(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - unsigned long flags; - struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); - - spin_lock_irqsave(&sm->lock, flags); - if (sm->scanning) { - spin_unlock_irqrestore(&sm->lock, flags); - return -EAGAIN; - } - spin_unlock_irqrestore(&sm->lock, flags); - return ieee80211_wx_get_scan(sm->ieee, info, data, extra); -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_scan_results); - -int -ieee80211softmac_wx_set_essid(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); - struct ieee80211softmac_auth_queue_item *authptr; - int length = 0; - DECLARE_MAC_BUF(mac); - -check_assoc_again: - mutex_lock(&sm->associnfo.mutex); - if((sm->associnfo.associating || sm->associnfo.associated) && - (data->essid.flags && data->essid.length)) { - dprintk(KERN_INFO PFX "Canceling existing associate request!\n"); - /* Cancel assoc work */ - cancel_delayed_work(&sm->associnfo.work); - /* We don't have to do this, but it's a little cleaner */ - list_for_each_entry(authptr, &sm->auth_queue, list) - cancel_delayed_work(&authptr->work); - sm->associnfo.bssvalid = 0; - sm->associnfo.bssfixed = 0; - sm->associnfo.associating = 0; - sm->associnfo.associated = 0; - /* We must unlock to avoid deadlocks with the assoc workqueue - * on the associnfo.mutex */ - mutex_unlock(&sm->associnfo.mutex); - flush_workqueue(sm->wq); - /* Avoid race! Check assoc status again. Maybe someone started an - * association while we flushed. */ - goto check_assoc_again; - } - - sm->associnfo.static_essid = 0; - sm->associnfo.assoc_wait = 0; - - if (data->essid.flags && data->essid.length) { - length = min((int)data->essid.length, IW_ESSID_MAX_SIZE); - if (length) { - memcpy(sm->associnfo.req_essid.data, extra, length); - sm->associnfo.static_essid = 1; - } - } - - /* set our requested ESSID length. - * If applicable, we have already copied the data in */ - sm->associnfo.req_essid.len = length; - - sm->associnfo.associating = 1; - /* queue lower level code to do work (if necessary) */ - queue_delayed_work(sm->wq, &sm->associnfo.work, 0); - - mutex_unlock(&sm->associnfo.mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_essid); - -int -ieee80211softmac_wx_get_essid(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct ieee80211softmac_device *sm = ieee80211_priv(net_dev); - - mutex_lock(&sm->associnfo.mutex); - /* If all fails, return ANY (empty) */ - data->essid.length = 0; - data->essid.flags = 0; /* active */ - - /* If we have a statically configured ESSID then return it */ - if (sm->associnfo.static_essid) { - data->essid.length = sm->associnfo.req_essid.len; - data->essid.flags = 1; /* active */ - memcpy(extra, sm->associnfo.req_essid.data, sm->associnfo.req_essid.len); - dprintk(KERN_INFO PFX "Getting essid from req_essid\n"); - } else if (sm->associnfo.associated || sm->associnfo.associating) { - /* If we're associating/associated, return that */ - data->essid.length = sm->associnfo.associate_essid.len; - data->essid.flags = 1; /* active */ - memcpy(extra, sm->associnfo.associate_essid.data, sm->associnfo.associate_essid.len); - dprintk(KERN_INFO PFX "Getting essid from associate_essid\n"); - } - mutex_unlock(&sm->associnfo.mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_essid); - -int -ieee80211softmac_wx_set_rate(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - struct ieee80211_device *ieee = mac->ieee; - unsigned long flags; - s32 in_rate = data->bitrate.value; - u8 rate; - int is_ofdm = 0; - int err = -EINVAL; - - if (in_rate == -1) { - if (ieee->modulation & IEEE80211_OFDM_MODULATION) - in_rate = 24000000; - else - in_rate = 11000000; - } - - switch (in_rate) { - case 1000000: - rate = IEEE80211_CCK_RATE_1MB; - break; - case 2000000: - rate = IEEE80211_CCK_RATE_2MB; - break; - case 5500000: - rate = IEEE80211_CCK_RATE_5MB; - break; - case 11000000: - rate = IEEE80211_CCK_RATE_11MB; - break; - case 6000000: - rate = IEEE80211_OFDM_RATE_6MB; - is_ofdm = 1; - break; - case 9000000: - rate = IEEE80211_OFDM_RATE_9MB; - is_ofdm = 1; - break; - case 12000000: - rate = IEEE80211_OFDM_RATE_12MB; - is_ofdm = 1; - break; - case 18000000: - rate = IEEE80211_OFDM_RATE_18MB; - is_ofdm = 1; - break; - case 24000000: - rate = IEEE80211_OFDM_RATE_24MB; - is_ofdm = 1; - break; - case 36000000: - rate = IEEE80211_OFDM_RATE_36MB; - is_ofdm = 1; - break; - case 48000000: - rate = IEEE80211_OFDM_RATE_48MB; - is_ofdm = 1; - break; - case 54000000: - rate = IEEE80211_OFDM_RATE_54MB; - is_ofdm = 1; - break; - default: - goto out; - } - - spin_lock_irqsave(&mac->lock, flags); - - /* Check if correct modulation for this PHY. */ - if (is_ofdm && !(ieee->modulation & IEEE80211_OFDM_MODULATION)) - goto out_unlock; - - mac->txrates.user_rate = rate; - ieee80211softmac_recalc_txrates(mac); - err = 0; - -out_unlock: - spin_unlock_irqrestore(&mac->lock, flags); -out: - return err; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_rate); - -int -ieee80211softmac_wx_get_rate(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - unsigned long flags; - int err = -EINVAL; - - spin_lock_irqsave(&mac->lock, flags); - - if (unlikely(!mac->running)) { - err = -ENODEV; - goto out_unlock; - } - - switch (mac->txrates.default_rate) { - case IEEE80211_CCK_RATE_1MB: - data->bitrate.value = 1000000; - break; - case IEEE80211_CCK_RATE_2MB: - data->bitrate.value = 2000000; - break; - case IEEE80211_CCK_RATE_5MB: - data->bitrate.value = 5500000; - break; - case IEEE80211_CCK_RATE_11MB: - data->bitrate.value = 11000000; - break; - case IEEE80211_OFDM_RATE_6MB: - data->bitrate.value = 6000000; - break; - case IEEE80211_OFDM_RATE_9MB: - data->bitrate.value = 9000000; - break; - case IEEE80211_OFDM_RATE_12MB: - data->bitrate.value = 12000000; - break; - case IEEE80211_OFDM_RATE_18MB: - data->bitrate.value = 18000000; - break; - case IEEE80211_OFDM_RATE_24MB: - data->bitrate.value = 24000000; - break; - case IEEE80211_OFDM_RATE_36MB: - data->bitrate.value = 36000000; - break; - case IEEE80211_OFDM_RATE_48MB: - data->bitrate.value = 48000000; - break; - case IEEE80211_OFDM_RATE_54MB: - data->bitrate.value = 54000000; - break; - default: - assert(0); - goto out_unlock; - } - err = 0; -out_unlock: - spin_unlock_irqrestore(&mac->lock, flags); - - return err; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_rate); - -int -ieee80211softmac_wx_get_wap(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - int err = 0; - - mutex_lock(&mac->associnfo.mutex); - if (mac->associnfo.bssvalid) - memcpy(data->ap_addr.sa_data, mac->associnfo.bssid, ETH_ALEN); - else - memset(data->ap_addr.sa_data, 0xff, ETH_ALEN); - data->ap_addr.sa_family = ARPHRD_ETHER; - mutex_unlock(&mac->associnfo.mutex); - - return err; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_wap); - -int -ieee80211softmac_wx_set_wap(struct net_device *net_dev, - struct iw_request_info *info, - union iwreq_data *data, - char *extra) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(net_dev); - - /* sanity check */ - if (data->ap_addr.sa_family != ARPHRD_ETHER) { - return -EINVAL; - } - - mutex_lock(&mac->associnfo.mutex); - if (is_broadcast_ether_addr(data->ap_addr.sa_data)) { - /* the bssid we have is not to be fixed any longer, - * and we should reassociate to the best AP. */ - mac->associnfo.bssfixed = 0; - /* force reassociation */ - mac->associnfo.bssvalid = 0; - if (mac->associnfo.associated) - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); - } else if (is_zero_ether_addr(data->ap_addr.sa_data)) { - /* the bssid we have is no longer fixed */ - mac->associnfo.bssfixed = 0; - } else { - if (!memcmp(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN)) { - if (mac->associnfo.associating || mac->associnfo.associated) { - /* bssid unchanged and associated or associating - just return */ - goto out; - } - } else { - /* copy new value in data->ap_addr.sa_data to bssid */ - memcpy(mac->associnfo.bssid, data->ap_addr.sa_data, ETH_ALEN); - } - /* tell the other code that this bssid should be used no matter what */ - mac->associnfo.bssfixed = 1; - /* queue associate if new bssid or (old one again and not associated) */ - queue_delayed_work(mac->wq, &mac->associnfo.work, 0); - } - - out: - mutex_unlock(&mac->associnfo.mutex); - - return 0; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_wap); - -int -ieee80211softmac_wx_set_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - unsigned long flags; - int err = 0; - char *buf; - int i; - - mutex_lock(&mac->associnfo.mutex); - spin_lock_irqsave(&mac->lock, flags); - /* bleh. shouldn't be locked for that kmalloc... */ - - if (wrqu->data.length) { - if ((wrqu->data.length < 2) || (extra[1]+2 != wrqu->data.length)) { - /* this is an IE, so the length must be - * correct. Is it possible though that - * more than one IE is passed in? - */ - err = -EINVAL; - goto out; - } - if (mac->wpa.IEbuflen <= wrqu->data.length) { - buf = kmalloc(wrqu->data.length, GFP_ATOMIC); - if (!buf) { - err = -ENOMEM; - goto out; - } - kfree(mac->wpa.IE); - mac->wpa.IE = buf; - mac->wpa.IEbuflen = wrqu->data.length; - } - memcpy(mac->wpa.IE, extra, wrqu->data.length); - dprintk(KERN_INFO PFX "generic IE set to "); - for (i=0;idata.length;i++) - dprintk("%.2x", (u8)mac->wpa.IE[i]); - dprintk("\n"); - mac->wpa.IElen = wrqu->data.length; - } else { - kfree(mac->wpa.IE); - mac->wpa.IE = NULL; - mac->wpa.IElen = 0; - mac->wpa.IEbuflen = 0; - } - - out: - spin_unlock_irqrestore(&mac->lock, flags); - mutex_unlock(&mac->associnfo.mutex); - - return err; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_genie); - -int -ieee80211softmac_wx_get_genie(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - unsigned long flags; - int err = 0; - int space = wrqu->data.length; - - mutex_lock(&mac->associnfo.mutex); - spin_lock_irqsave(&mac->lock, flags); - - wrqu->data.length = 0; - - if (mac->wpa.IE && mac->wpa.IElen) { - wrqu->data.length = mac->wpa.IElen; - if (mac->wpa.IElen <= space) - memcpy(extra, mac->wpa.IE, mac->wpa.IElen); - else - err = -E2BIG; - } - spin_unlock_irqrestore(&mac->lock, flags); - mutex_unlock(&mac->associnfo.mutex); - - return err; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_get_genie); - -int -ieee80211softmac_wx_set_mlme(struct net_device *dev, - struct iw_request_info *info, - union iwreq_data *wrqu, - char *extra) -{ - struct ieee80211softmac_device *mac = ieee80211_priv(dev); - struct iw_mlme *mlme = (struct iw_mlme *)extra; - u16 reason = mlme->reason_code; - struct ieee80211softmac_network *net; - int err = -EINVAL; - - mutex_lock(&mac->associnfo.mutex); - - if (memcmp(mac->associnfo.bssid, mlme->addr.sa_data, ETH_ALEN)) { - printk(KERN_DEBUG PFX "wx_set_mlme: requested operation on net we don't use\n"); - goto out; - } - - switch (mlme->cmd) { - case IW_MLME_DEAUTH: - net = ieee80211softmac_get_network_by_bssid_locked(mac, mlme->addr.sa_data); - if (!net) { - printk(KERN_DEBUG PFX "wx_set_mlme: we should know the net here...\n"); - goto out; - } - err = ieee80211softmac_deauth_req(mac, net, reason); - goto out; - case IW_MLME_DISASSOC: - ieee80211softmac_send_disassoc_req(mac, reason); - mac->associnfo.associated = 0; - mac->associnfo.associating = 0; - err = 0; - goto out; - default: - err = -EOPNOTSUPP; - } - -out: - mutex_unlock(&mac->associnfo.mutex); - - return err; -} -EXPORT_SYMBOL_GPL(ieee80211softmac_wx_set_mlme); -- cgit v1.2.3 From d9357136ac4729f589543afb6b1d17d443ae4f71 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 4 Mar 2008 15:26:15 -0800 Subject: the scheduled rc80211-simple.c removal Signed-off-by: Adrian Bunk Signed-off-by: Andrew Morton Signed-off-by: John W. Linville --- Documentation/feature-removal-schedule.txt | 10 - net/mac80211/Kconfig | 19 -- net/mac80211/Makefile | 2 - net/mac80211/ieee80211.c | 9 +- net/mac80211/ieee80211_rate.h | 15 -- net/mac80211/rc80211_simple.c | 394 ----------------------------- 6 files changed, 1 insertion(+), 448 deletions(-) delete mode 100644 net/mac80211/rc80211_simple.c (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 2cf4d7ad7b0b..7279595b96c3 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -230,16 +230,6 @@ Who: Jean Delvare --------------------------- -What: rc80211-simple rate control algorithm for mac80211 -When: 2.6.26 -Files: net/mac80211/rc80211-simple.c -Why: This algorithm was provided for reference but always exhibited bad - responsiveness and performance and has some serious flaws. It has been - replaced by rc80211-pid. -Who: Stefano Brivio - ---------------------------- - What (Why): - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files (superseded by xt_TOS/xt_tos target & match) diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 3c3f62faae1e..520a5180a4f6 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig @@ -32,15 +32,6 @@ config MAC80211_RC_DEFAULT_PID default rate control algorithm. You should choose this unless you know what you are doing. -config MAC80211_RC_DEFAULT_SIMPLE - bool "Simple rate control algorithm" - select MAC80211_RC_SIMPLE - ---help--- - Select the simple rate control as the default rate - control algorithm. Note that this is a non-responsive, - dumb algorithm. You should choose the PID rate control - instead. - config MAC80211_RC_DEFAULT_NONE bool "No default algorithm" depends on EMBEDDED @@ -57,7 +48,6 @@ comment "build the algorithm into mac80211." config MAC80211_RC_DEFAULT string default "pid" if MAC80211_RC_DEFAULT_PID - default "simple" if MAC80211_RC_DEFAULT_SIMPLE default "" config MAC80211_RC_PID @@ -70,15 +60,6 @@ config MAC80211_RC_PID Say Y or M unless you're sure you want to use a different rate control algorithm. -config MAC80211_RC_SIMPLE - tristate "Simple rate control algorithm (DEPRECATED)" - ---help--- - This option enables a very simple, non-responsive TX - rate control algorithm. This algorithm is deprecated - and will be removed from the kernel in the near future. - It has been replaced by the PID algorithm. - - Say N unless you know what you are doing. endmenu config MAC80211_MESH diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 829ce4256b76..70f4b26c2d87 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile @@ -44,9 +44,7 @@ mac80211-$(CONFIG_MAC80211_MESH) += \ # Build rate control algorithm(s) -CFLAGS_rc80211_simple.o += -DRC80211_SIMPLE_COMPILE CFLAGS_rc80211_pid_algo.o += -DRC80211_PID_COMPILE -mac80211-$(CONFIG_MAC80211_RC_SIMPLE) += rc80211_simple.o mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc-pid-$(CONFIG_MAC80211_RC_PID)) # Modular rate algorithms are assigned to mac80211-m - make separate modules diff --git a/net/mac80211/ieee80211.c b/net/mac80211/ieee80211.c index 484b063a3538..55b63712e48c 100644 --- a/net/mac80211/ieee80211.c +++ b/net/mac80211/ieee80211.c @@ -1803,13 +1803,9 @@ static int __init ieee80211_init(void) BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb)); - ret = rc80211_simple_init(); - if (ret) - goto out; - ret = rc80211_pid_init(); if (ret) - goto out_cleanup_simple; + goto out; ret = ieee80211_wme_register(); if (ret) { @@ -1824,15 +1820,12 @@ static int __init ieee80211_init(void) out_cleanup_pid: rc80211_pid_exit(); - out_cleanup_simple: - rc80211_simple_exit(); out: return ret; } static void __exit ieee80211_exit(void) { - rc80211_simple_exit(); rc80211_pid_exit(); if (mesh_allocated) diff --git a/net/mac80211/ieee80211_rate.h b/net/mac80211/ieee80211_rate.h index bfd0a1982e4a..5b45f33cb766 100644 --- a/net/mac80211/ieee80211_rate.h +++ b/net/mac80211/ieee80211_rate.h @@ -171,21 +171,6 @@ void rate_control_deinitialize(struct ieee80211_local *local); /* Rate control algorithms */ -#if defined(RC80211_SIMPLE_COMPILE) || \ - (defined(CONFIG_MAC80211_RC_SIMPLE) && \ - !defined(CONFIG_MAC80211_RC_SIMPLE_MODULE)) -extern int rc80211_simple_init(void); -extern void rc80211_simple_exit(void); -#else -static inline int rc80211_simple_init(void) -{ - return 0; -} -static inline void rc80211_simple_exit(void) -{ -} -#endif - #if defined(RC80211_PID_COMPILE) || \ (defined(CONFIG_MAC80211_RC_PID) && \ !defined(CONFIG_MAC80211_RC_PID_MODULE)) diff --git a/net/mac80211/rc80211_simple.c b/net/mac80211/rc80211_simple.c deleted file mode 100644 index 4f72fdca7f12..000000000000 --- a/net/mac80211/rc80211_simple.c +++ /dev/null @@ -1,394 +0,0 @@ -/* - * Copyright 2002-2005, Instant802 Networks, Inc. - * Copyright 2005, Devicescape Software, Inc. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include "ieee80211_i.h" -#include "ieee80211_rate.h" -#include "debugfs.h" - - -/* This is a minimal implementation of TX rate controlling that can be used - * as the default when no improved mechanisms are available. */ - -#define RATE_CONTROL_NUM_DOWN 20 -#define RATE_CONTROL_NUM_UP 15 - -#define RATE_CONTROL_EMERG_DEC 2 -#define RATE_CONTROL_INTERVAL (HZ / 20) -#define RATE_CONTROL_MIN_TX 10 - -static void rate_control_rate_inc(struct ieee80211_local *local, - struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_supported_band *sband; - int i = sta->txrate_idx; - int maxrate; - - sdata = sta->sdata; - if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { - /* forced unicast rate - do not change STA rate */ - return; - } - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - maxrate = sdata->bss ? sdata->bss->max_ratectrl_rateidx : -1; - - if (i > sband->n_bitrates) - i = sband->n_bitrates - 2; - - while (i + 1 < sband->n_bitrates) { - i++; - if (rate_supported(sta, sband->band, i) && - (maxrate < 0 || i <= maxrate)) { - sta->txrate_idx = i; - break; - } - } -} - - -static void rate_control_rate_dec(struct ieee80211_local *local, - struct sta_info *sta) -{ - struct ieee80211_sub_if_data *sdata; - struct ieee80211_supported_band *sband; - int i = sta->txrate_idx; - - sdata = sta->sdata; - if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) { - /* forced unicast rate - do not change STA rate */ - return; - } - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - if (i > sband->n_bitrates) - i = sband->n_bitrates; - - while (i > 0) { - i--; - if (rate_supported(sta, sband->band, i)) { - sta->txrate_idx = i; - break; - } - } -} - -struct global_rate_control { - int dummy; -}; - -struct sta_rate_control { - unsigned long last_rate_change; - u32 tx_num_failures; - u32 tx_num_xmit; - - unsigned long avg_rate_update; - u32 tx_avg_rate_sum; - u32 tx_avg_rate_num; - -#ifdef CONFIG_MAC80211_DEBUGFS - struct dentry *tx_avg_rate_sum_dentry; - struct dentry *tx_avg_rate_num_dentry; -#endif -}; - - -static void rate_control_simple_tx_status(void *priv, struct net_device *dev, - struct sk_buff *skb, - struct ieee80211_tx_status *status) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct sta_info *sta; - struct sta_rate_control *srctrl; - - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - - if (!sta) - goto unlock; - - srctrl = sta->rate_ctrl_priv; - srctrl->tx_num_xmit++; - if (status->excessive_retries) { - srctrl->tx_num_failures++; - sta->tx_retry_failed++; - sta->tx_num_consecutive_failures++; - sta->tx_num_mpdu_fail++; - } else { - sta->tx_num_consecutive_failures = 0; - sta->tx_num_mpdu_ok++; - } - sta->tx_retry_count += status->retry_count; - sta->tx_num_mpdu_fail += status->retry_count; - - if (time_after(jiffies, - srctrl->last_rate_change + RATE_CONTROL_INTERVAL) && - srctrl->tx_num_xmit > RATE_CONTROL_MIN_TX) { - u32 per_failed; - srctrl->last_rate_change = jiffies; - - per_failed = (100 * sta->tx_num_mpdu_fail) / - (sta->tx_num_mpdu_fail + sta->tx_num_mpdu_ok); - /* TODO: calculate average per_failed to make adjusting - * parameters easier */ -#if 0 - if (net_ratelimit()) { - printk(KERN_DEBUG "MPDU fail=%d ok=%d per_failed=%d\n", - sta->tx_num_mpdu_fail, sta->tx_num_mpdu_ok, - per_failed); - } -#endif - - /* - * XXX: Make these configurable once we have an - * interface to the rate control algorithms - */ - if (per_failed > RATE_CONTROL_NUM_DOWN) { - rate_control_rate_dec(local, sta); - } else if (per_failed < RATE_CONTROL_NUM_UP) { - rate_control_rate_inc(local, sta); - } - srctrl->tx_avg_rate_sum += status->control.tx_rate->bitrate; - srctrl->tx_avg_rate_num++; - srctrl->tx_num_failures = 0; - srctrl->tx_num_xmit = 0; - } else if (sta->tx_num_consecutive_failures >= - RATE_CONTROL_EMERG_DEC) { - rate_control_rate_dec(local, sta); - } - - if (time_after(jiffies, srctrl->avg_rate_update + 60 * HZ)) { - srctrl->avg_rate_update = jiffies; - if (srctrl->tx_avg_rate_num > 0) { -#ifdef CONFIG_MAC80211_VERBOSE_DEBUG - DECLARE_MAC_BUF(mac); - printk(KERN_DEBUG "%s: STA %s Average rate: " - "%d (%d/%d)\n", - dev->name, print_mac(mac, sta->addr), - srctrl->tx_avg_rate_sum / - srctrl->tx_avg_rate_num, - srctrl->tx_avg_rate_sum, - srctrl->tx_avg_rate_num); -#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */ - srctrl->tx_avg_rate_sum = 0; - srctrl->tx_avg_rate_num = 0; - } - } - - unlock: - rcu_read_unlock(); -} - - -static void -rate_control_simple_get_rate(void *priv, struct net_device *dev, - struct ieee80211_supported_band *sband, - struct sk_buff *skb, - struct rate_selection *sel) -{ - struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; - struct ieee80211_sub_if_data *sdata; - struct sta_info *sta; - int rateidx; - u16 fc; - - rcu_read_lock(); - - sta = sta_info_get(local, hdr->addr1); - - /* Send management frames and broadcast/multicast data using lowest - * rate. */ - fc = le16_to_cpu(hdr->frame_control); - if ((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA || - is_multicast_ether_addr(hdr->addr1) || !sta) { - sel->rate = rate_lowest(local, sband, sta); - rcu_read_unlock(); - return; - } - - /* If a forced rate is in effect, select it. */ - sdata = IEEE80211_DEV_TO_SUB_IF(dev); - if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) - sta->txrate_idx = sdata->bss->force_unicast_rateidx; - - rateidx = sta->txrate_idx; - - if (rateidx >= sband->n_bitrates) - rateidx = sband->n_bitrates - 1; - - sta->last_txrate_idx = rateidx; - - rcu_read_unlock(); - - sel->rate = &sband->bitrates[rateidx]; -} - - -static void rate_control_simple_rate_init(void *priv, void *priv_sta, - struct ieee80211_local *local, - struct sta_info *sta) -{ - struct ieee80211_supported_band *sband; - - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - /* TODO: This routine should consider using RSSI from previous packets - * as we need to have IEEE 802.1X auth succeed immediately after assoc.. - * Until that method is implemented, we will use the lowest supported rate - * as a workaround, */ - sta->txrate_idx = rate_lowest_index(local, sband, sta); -} - - -static void * rate_control_simple_alloc(struct ieee80211_local *local) -{ - struct global_rate_control *rctrl; - - rctrl = kzalloc(sizeof(*rctrl), GFP_ATOMIC); - - return rctrl; -} - - -static void rate_control_simple_free(void *priv) -{ - struct global_rate_control *rctrl = priv; - kfree(rctrl); -} - - -static void rate_control_simple_clear(void *priv) -{ -} - - -static void * rate_control_simple_alloc_sta(void *priv, gfp_t gfp) -{ - struct sta_rate_control *rctrl; - - rctrl = kzalloc(sizeof(*rctrl), gfp); - - return rctrl; -} - - -static void rate_control_simple_free_sta(void *priv, void *priv_sta) -{ - struct sta_rate_control *rctrl = priv_sta; - kfree(rctrl); -} - -#ifdef CONFIG_MAC80211_DEBUGFS - -static int open_file_generic(struct inode *inode, struct file *file) -{ - file->private_data = inode->i_private; - return 0; -} - -static ssize_t sta_tx_avg_rate_sum_read(struct file *file, - char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct sta_rate_control *srctrl = file->private_data; - char buf[20]; - - sprintf(buf, "%d\n", srctrl->tx_avg_rate_sum); - return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); -} - -static const struct file_operations sta_tx_avg_rate_sum_ops = { - .read = sta_tx_avg_rate_sum_read, - .open = open_file_generic, -}; - -static ssize_t sta_tx_avg_rate_num_read(struct file *file, - char __user *userbuf, - size_t count, loff_t *ppos) -{ - struct sta_rate_control *srctrl = file->private_data; - char buf[20]; - - sprintf(buf, "%d\n", srctrl->tx_avg_rate_num); - return simple_read_from_buffer(userbuf, count, ppos, buf, strlen(buf)); -} - -static const struct file_operations sta_tx_avg_rate_num_ops = { - .read = sta_tx_avg_rate_num_read, - .open = open_file_generic, -}; - -static void rate_control_simple_add_sta_debugfs(void *priv, void *priv_sta, - struct dentry *dir) -{ - struct sta_rate_control *srctrl = priv_sta; - - srctrl->tx_avg_rate_num_dentry = - debugfs_create_file("rc_simple_sta_tx_avg_rate_num", 0400, - dir, srctrl, &sta_tx_avg_rate_num_ops); - srctrl->tx_avg_rate_sum_dentry = - debugfs_create_file("rc_simple_sta_tx_avg_rate_sum", 0400, - dir, srctrl, &sta_tx_avg_rate_sum_ops); -} - -static void rate_control_simple_remove_sta_debugfs(void *priv, void *priv_sta) -{ - struct sta_rate_control *srctrl = priv_sta; - - debugfs_remove(srctrl->tx_avg_rate_sum_dentry); - debugfs_remove(srctrl->tx_avg_rate_num_dentry); -} -#endif - -static struct rate_control_ops mac80211_rcsimple = { - .name = "simple", - .tx_status = rate_control_simple_tx_status, - .get_rate = rate_control_simple_get_rate, - .rate_init = rate_control_simple_rate_init, - .clear = rate_control_simple_clear, - .alloc = rate_control_simple_alloc, - .free = rate_control_simple_free, - .alloc_sta = rate_control_simple_alloc_sta, - .free_sta = rate_control_simple_free_sta, -#ifdef CONFIG_MAC80211_DEBUGFS - .add_sta_debugfs = rate_control_simple_add_sta_debugfs, - .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs, -#endif -}; - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("Simple rate control algorithm"); - -int __init rc80211_simple_init(void) -{ - return ieee80211_rate_control_register(&mac80211_rcsimple); -} - -void rc80211_simple_exit(void) -{ - ieee80211_rate_control_unregister(&mac80211_rcsimple); -} - -#ifdef CONFIG_MAC80211_RC_SIMPLE_MODULE -module_init(rc80211_simple_init); -module_exit(rc80211_simple_exit); -#endif -- cgit v1.2.3 From 548c36e983f346621b5cb9ab031e4383e9996576 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 30 Jan 2008 22:04:05 -0800 Subject: sk98lin: remove obsolete driver All the hardware supported by this driver is now supported by the skge driver. The last remaining issue was support for ancient dual port SysKonnect fiber boards, and the skge driver now does these correctly (p.s. sk98lin was always broken on these old dual port boards anyway). Signed-off-by: Stephen Hemminger Signed-off-by: Jeff Garzik --- Documentation/feature-removal-schedule.txt | 10 - drivers/net/Kconfig | 87 - drivers/net/Makefile | 1 - drivers/net/sk98lin/Makefile | 87 - drivers/net/sk98lin/h/lm80.h | 179 - drivers/net/sk98lin/h/skaddr.h | 285 - drivers/net/sk98lin/h/skcsum.h | 213 - drivers/net/sk98lin/h/skdebug.h | 74 - drivers/net/sk98lin/h/skdrv1st.h | 188 - drivers/net/sk98lin/h/skdrv2nd.h | 447 -- drivers/net/sk98lin/h/skerror.h | 55 - drivers/net/sk98lin/h/skgedrv.h | 51 - drivers/net/sk98lin/h/skgehw.h | 2126 -------- drivers/net/sk98lin/h/skgehwt.h | 48 - drivers/net/sk98lin/h/skgei2c.h | 210 - drivers/net/sk98lin/h/skgeinit.h | 797 --- drivers/net/sk98lin/h/skgepnm2.h | 334 -- drivers/net/sk98lin/h/skgepnmi.h | 962 ---- drivers/net/sk98lin/h/skgesirq.h | 110 - drivers/net/sk98lin/h/ski2c.h | 174 - drivers/net/sk98lin/h/skqueue.h | 94 - drivers/net/sk98lin/h/skrlmt.h | 438 -- drivers/net/sk98lin/h/sktimer.h | 63 - drivers/net/sk98lin/h/sktypes.h | 69 - drivers/net/sk98lin/h/skversion.h | 38 - drivers/net/sk98lin/h/skvpd.h | 248 - drivers/net/sk98lin/h/xmac_ii.h | 1579 ------ drivers/net/sk98lin/skaddr.c | 1788 ------ drivers/net/sk98lin/skdim.c | 742 --- drivers/net/sk98lin/skethtool.c | 627 --- drivers/net/sk98lin/skge.c | 5218 ------------------ drivers/net/sk98lin/skgehwt.c | 171 - drivers/net/sk98lin/skgeinit.c | 2005 ------- drivers/net/sk98lin/skgemib.c | 1075 ---- drivers/net/sk98lin/skgepnmi.c | 8198 ---------------------------- drivers/net/sk98lin/skgesirq.c | 2229 -------- drivers/net/sk98lin/ski2c.c | 1296 ----- drivers/net/sk98lin/sklm80.c | 141 - drivers/net/sk98lin/skqueue.c | 179 - drivers/net/sk98lin/skrlmt.c | 3257 ----------- drivers/net/sk98lin/sktimer.c | 250 - drivers/net/sk98lin/skvpd.c | 1091 ---- drivers/net/sk98lin/skxmac2.c | 4160 -------------- 43 files changed, 41394 deletions(-) delete mode 100644 drivers/net/sk98lin/Makefile delete mode 100644 drivers/net/sk98lin/h/lm80.h delete mode 100644 drivers/net/sk98lin/h/skaddr.h delete mode 100644 drivers/net/sk98lin/h/skcsum.h delete mode 100644 drivers/net/sk98lin/h/skdebug.h delete mode 100644 drivers/net/sk98lin/h/skdrv1st.h delete mode 100644 drivers/net/sk98lin/h/skdrv2nd.h delete mode 100644 drivers/net/sk98lin/h/skerror.h delete mode 100644 drivers/net/sk98lin/h/skgedrv.h delete mode 100644 drivers/net/sk98lin/h/skgehw.h delete mode 100644 drivers/net/sk98lin/h/skgehwt.h delete mode 100644 drivers/net/sk98lin/h/skgei2c.h delete mode 100644 drivers/net/sk98lin/h/skgeinit.h delete mode 100644 drivers/net/sk98lin/h/skgepnm2.h delete mode 100644 drivers/net/sk98lin/h/skgepnmi.h delete mode 100644 drivers/net/sk98lin/h/skgesirq.h delete mode 100644 drivers/net/sk98lin/h/ski2c.h delete mode 100644 drivers/net/sk98lin/h/skqueue.h delete mode 100644 drivers/net/sk98lin/h/skrlmt.h delete mode 100644 drivers/net/sk98lin/h/sktimer.h delete mode 100644 drivers/net/sk98lin/h/sktypes.h delete mode 100644 drivers/net/sk98lin/h/skversion.h delete mode 100644 drivers/net/sk98lin/h/skvpd.h delete mode 100644 drivers/net/sk98lin/h/xmac_ii.h delete mode 100644 drivers/net/sk98lin/skaddr.c delete mode 100644 drivers/net/sk98lin/skdim.c delete mode 100644 drivers/net/sk98lin/skethtool.c delete mode 100644 drivers/net/sk98lin/skge.c delete mode 100644 drivers/net/sk98lin/skgehwt.c delete mode 100644 drivers/net/sk98lin/skgeinit.c delete mode 100644 drivers/net/sk98lin/skgemib.c delete mode 100644 drivers/net/sk98lin/skgepnmi.c delete mode 100644 drivers/net/sk98lin/skgesirq.c delete mode 100644 drivers/net/sk98lin/ski2c.c delete mode 100644 drivers/net/sk98lin/sklm80.c delete mode 100644 drivers/net/sk98lin/skqueue.c delete mode 100644 drivers/net/sk98lin/skrlmt.c delete mode 100644 drivers/net/sk98lin/sktimer.c delete mode 100644 drivers/net/sk98lin/skvpd.c delete mode 100644 drivers/net/sk98lin/skxmac2.c (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index c1d1fd0c299b..57eadfdfd88b 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -213,14 +213,6 @@ Who: linuxppc-dev@ozlabs.org --------------------------- -What: sk98lin network driver -When: Feburary 2008 -Why: In kernel tree version of driver is unmaintained. Sk98lin driver - replaced by the skge driver. -Who: Stephen Hemminger - ---------------------------- - What: i386/x86_64 bzImage symlinks When: April 2008 @@ -231,8 +223,6 @@ Who: Thomas Gleixner --------------------------- ---------------------------- - What: i2c-i810, i2c-prosavage and i2c-savage4 When: May 2008 Why: These drivers are superseded by i810fb, intelfb and savagefb. diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index fe7b5ec09708..978e72ab39c2 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig @@ -2220,93 +2220,6 @@ config SKY2_DEBUG If unsure, say N. -config SK98LIN - tristate "Marvell Yukon Chipset / SysKonnect SK-98xx Support (DEPRECATED)" - depends on PCI - ---help--- - Say Y here if you have a Marvell Yukon or SysKonnect SK-98xx/SK-95xx - compliant Gigabit Ethernet Adapter. - - This driver supports the original Yukon chipset. This driver is - deprecated and will be removed from the kernel in the near future, - it has been replaced by the skge driver. skge is cleaner and - seems to work better. - - This driver does not support the newer Yukon2 chipset. A separate - driver, sky2, is provided to support Yukon2-based adapters. - - The following adapters are supported by this driver: - - 3Com 3C940 Gigabit LOM Ethernet Adapter - - 3Com 3C941 Gigabit LOM Ethernet Adapter - - Allied Telesyn AT-2970LX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970LX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970SX/2SC Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2970TX/2TX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971SX Gigabit Ethernet Adapter - - Allied Telesyn AT-2971T Gigabit Ethernet Adapter - - Belkin Gigabit Desktop Card 10/100/1000Base-T Adapter, Copper RJ-45 - - EG1032 v2 Instant Gigabit Network Adapter - - EG1064 v2 Instant Gigabit Network Adapter - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Abit) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Albatron) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Asus) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (ECS) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Epox) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Foxconn) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Gigabyte) - - Marvell 88E8001 Gigabit LOM Ethernet Adapter (Iwill) - - Marvell 88E8050 Gigabit LOM Ethernet Adapter (Intel) - - Marvell RDK-8001 Adapter - - Marvell RDK-8002 Adapter - - Marvell RDK-8003 Adapter - - Marvell RDK-8004 Adapter - - Marvell RDK-8006 Adapter - - Marvell RDK-8007 Adapter - - Marvell RDK-8008 Adapter - - Marvell RDK-8009 Adapter - - Marvell RDK-8010 Adapter - - Marvell RDK-8011 Adapter - - Marvell RDK-8012 Adapter - - Marvell RDK-8052 Adapter - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (32 bit) - - Marvell Yukon Gigabit Ethernet 10/100/1000Base-T Adapter (64 bit) - - N-Way PCI-Bus Giga-Card 1000/100/10Mbps(L) - - SK-9521 10/100/1000Base-T Adapter - - SK-9521 V2.0 10/100/1000Base-T Adapter - - SK-9821 Gigabit Ethernet Server Adapter (SK-NET GE-T) - - SK-9821 V2.0 Gigabit Ethernet 10/100/1000Base-T Adapter - - SK-9822 Gigabit Ethernet Server Adapter (SK-NET GE-T dual link) - - SK-9841 Gigabit Ethernet Server Adapter (SK-NET GE-LX) - - SK-9841 V2.0 Gigabit Ethernet 1000Base-LX Adapter - - SK-9842 Gigabit Ethernet Server Adapter (SK-NET GE-LX dual link) - - SK-9843 Gigabit Ethernet Server Adapter (SK-NET GE-SX) - - SK-9843 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9844 Gigabit Ethernet Server Adapter (SK-NET GE-SX dual link) - - SK-9851 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9861 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition) - - SK-9861 V2.0 Gigabit Ethernet 1000Base-SX Adapter - - SK-9862 Gigabit Ethernet Server Adapter (SK-NET GE-SX Volition dual link) - - SK-9871 Gigabit Ethernet Server Adapter (SK-NET GE-ZX) - - SK-9871 V2.0 Gigabit Ethernet 1000Base-ZX Adapter - - SK-9872 Gigabit Ethernet Server Adapter (SK-NET GE-ZX dual link) - - SMC EZ Card 1000 (SMC9452TXV.2) - - The adapters support Jumbo Frames. - The dual link adapters support link-failover and dual port features. - Both Marvell Yukon and SysKonnect SK-98xx/SK-95xx adapters support - the scatter-gather functionality with sendfile(). Please refer to - for more information about - optional driver parameters. - Questions concerning this driver may be addressed to: - - - If you want to compile this driver as a module ( = code which can be - inserted in and removed from the running kernel whenever you want), - say M here and read . The module will - be called sk98lin. This is recommended. - config VIA_VELOCITY tristate "VIA Velocity support" depends on PCI diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 3b1ea321dc05..b8756eb9030c 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -75,7 +75,6 @@ ps3_gelic-objs += ps3_gelic_net.o $(gelic_wireless-y) obj-$(CONFIG_TC35815) += tc35815.o obj-$(CONFIG_SKGE) += skge.o obj-$(CONFIG_SKY2) += sky2.o -obj-$(CONFIG_SK98LIN) += sk98lin/ obj-$(CONFIG_SKFP) += skfp/ obj-$(CONFIG_VIA_RHINE) += via-rhine.o obj-$(CONFIG_VIA_VELOCITY) += via-velocity.o diff --git a/drivers/net/sk98lin/Makefile b/drivers/net/sk98lin/Makefile deleted file mode 100644 index afd900d5d730..000000000000 --- a/drivers/net/sk98lin/Makefile +++ /dev/null @@ -1,87 +0,0 @@ -# -# Makefile for the SysKonnect SK-98xx device driver. -# - - -# -# Standalone driver params -# SKPARAM += -DSK_KERNEL_24 -# SKPARAM += -DSK_KERNEL_24_26 -# SKPARAM += -DSK_KERNEL_26 -# SKPARAM += -DSK_KERNEL_22_24 - -obj-$(CONFIG_SK98LIN) += sk98lin.o -sk98lin-objs := \ - skge.o \ - skethtool.o \ - skdim.o \ - skaddr.o \ - skgehwt.o \ - skgeinit.o \ - skgepnmi.o \ - skgesirq.o \ - ski2c.o \ - sklm80.o \ - skqueue.o \ - skrlmt.o \ - sktimer.o \ - skvpd.o \ - skxmac2.o - -# DBGDEF = \ -# -DDEBUG - -ifdef DEBUG -DBGDEF += \ --DSK_DEBUG_CHKMOD=0x00000000L \ --DSK_DEBUG_CHKCAT=0x00000000L -endif - - -# **** possible debug modules for SK_DEBUG_CHKMOD ***************** -# SK_DBGMOD_MERR 0x00000001L /* general module error indication */ -# SK_DBGMOD_HWM 0x00000002L /* Hardware init module */ -# SK_DBGMOD_RLMT 0x00000004L /* RLMT module */ -# SK_DBGMOD_VPD 0x00000008L /* VPD module */ -# SK_DBGMOD_I2C 0x00000010L /* I2C module */ -# SK_DBGMOD_PNMI 0x00000020L /* PNMI module */ -# SK_DBGMOD_CSUM 0x00000040L /* CSUM module */ -# SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ -# SK_DBGMOD_DRV 0x00010000L /* DRV module */ - -# **** possible debug categories for SK_DEBUG_CHKCAT ************** -# *** common modules *** -# SK_DBGCAT_INIT 0x00000001L module/driver initialization -# SK_DBGCAT_CTRL 0x00000002L controlling: add/rmv MCA/MAC and other controls (IOCTL) -# SK_DBGCAT_ERR 0x00000004L error handling paths -# SK_DBGCAT_TX 0x00000008L transmit path -# SK_DBGCAT_RX 0x00000010L receive path -# SK_DBGCAT_IRQ 0x00000020L general IRQ handling -# SK_DBGCAT_QUEUE 0x00000040L any queue management -# SK_DBGCAT_DUMP 0x00000080L large data output e.g. hex dump -# SK_DBGCAT_FATAL 0x00000100L large data output e.g. hex dump - -# *** driver (file skge.c) *** -# SK_DBGCAT_DRV_ENTRY 0x00010000 entry points -# SK_DBGCAT_DRV_??? 0x00020000 not used -# SK_DBGCAT_DRV_MCA 0x00040000 multicast -# SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 tx path -# SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 rx path -# SK_DBGCAT_DRV_PROGRESS 0x00200000 general runtime -# SK_DBGCAT_DRV_??? 0x00400000 not used -# SK_DBGCAT_DRV_PROM 0x00800000 promiscuous mode -# SK_DBGCAT_DRV_TX_FRAME 0x01000000 display tx frames -# SK_DBGCAT_DRV_ERROR 0x02000000 error conditions -# SK_DBGCAT_DRV_INT_SRC 0x04000000 interrupts sources -# SK_DBGCAT_DRV_EVENT 0x08000000 driver events - -EXTRA_CFLAGS += -Idrivers/net/sk98lin -DSK_DIAG_SUPPORT -DGENESIS -DYUKON $(DBGDEF) $(SKPARAM) - -clean: - rm -f core *.o *.a *.s - - - - - - diff --git a/drivers/net/sk98lin/h/lm80.h b/drivers/net/sk98lin/h/lm80.h deleted file mode 100644 index 4e2dbbf78000..000000000000 --- a/drivers/net/sk98lin/h/lm80.h +++ /dev/null @@ -1,179 +0,0 @@ -/****************************************************************************** - * - * Name: lm80.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.6 $ - * Date: $Date: 2003/05/13 17:26:52 $ - * Purpose: Contains all defines for the LM80 Chip - * (National Semiconductor). - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_LM80_H -#define __INC_LM80_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -/* - * LM80 register definition - * - * All registers are 8 bit wide - */ -#define LM80_CFG 0x00 /* Configuration Register */ -#define LM80_ISRC_1 0x01 /* Interrupt Status Register 1 */ -#define LM80_ISRC_2 0x02 /* Interrupt Status Register 2 */ -#define LM80_IMSK_1 0x03 /* Interrupt Mask Register 1 */ -#define LM80_IMSK_2 0x04 /* Interrupt Mask Register 2 */ -#define LM80_FAN_CTRL 0x05 /* Fan Devisor/RST#/OS# Register */ -#define LM80_TEMP_CTRL 0x06 /* OS# Config, Temp Res. Reg */ - /* 0x07 - 0x1f reserved */ - /* current values */ -#define LM80_VT0_IN 0x20 /* current Voltage 0 value */ -#define LM80_VT1_IN 0x21 /* current Voltage 1 value */ -#define LM80_VT2_IN 0x22 /* current Voltage 2 value */ -#define LM80_VT3_IN 0x23 /* current Voltage 3 value */ -#define LM80_VT4_IN 0x24 /* current Voltage 4 value */ -#define LM80_VT5_IN 0x25 /* current Voltage 5 value */ -#define LM80_VT6_IN 0x26 /* current Voltage 6 value */ -#define LM80_TEMP_IN 0x27 /* current Temperature value */ -#define LM80_FAN1_IN 0x28 /* current Fan 1 count */ -#define LM80_FAN2_IN 0x29 /* current Fan 2 count */ - /* limit values */ -#define LM80_VT0_HIGH_LIM 0x2a /* high limit val for Voltage 0 */ -#define LM80_VT0_LOW_LIM 0x2b /* low limit val for Voltage 0 */ -#define LM80_VT1_HIGH_LIM 0x2c /* high limit val for Voltage 1 */ -#define LM80_VT1_LOW_LIM 0x2d /* low limit val for Voltage 1 */ -#define LM80_VT2_HIGH_LIM 0x2e /* high limit val for Voltage 2 */ -#define LM80_VT2_LOW_LIM 0x2f /* low limit val for Voltage 2 */ -#define LM80_VT3_HIGH_LIM 0x30 /* high limit val for Voltage 3 */ -#define LM80_VT3_LOW_LIM 0x31 /* low limit val for Voltage 3 */ -#define LM80_VT4_HIGH_LIM 0x32 /* high limit val for Voltage 4 */ -#define LM80_VT4_LOW_LIM 0x33 /* low limit val for Voltage 4 */ -#define LM80_VT5_HIGH_LIM 0x34 /* high limit val for Voltage 5 */ -#define LM80_VT5_LOW_LIM 0x35 /* low limit val for Voltage 5 */ -#define LM80_VT6_HIGH_LIM 0x36 /* high limit val for Voltage 6 */ -#define LM80_VT6_LOW_LIM 0x37 /* low limit val for Voltage 6 */ -#define LM80_THOT_LIM_UP 0x38 /* hot temperature limit (high) */ -#define LM80_THOT_LIM_LO 0x39 /* hot temperature limit (low) */ -#define LM80_TOS_LIM_UP 0x3a /* OS temperature limit (high) */ -#define LM80_TOS_LIM_LO 0x3b /* OS temperature limit (low) */ -#define LM80_FAN1_COUNT_LIM 0x3c /* Fan 1 count limit (high) */ -#define LM80_FAN2_COUNT_LIM 0x3d /* Fan 2 count limit (low) */ - /* 0x3e - 0x3f reserved */ - -/* - * LM80 bit definitions - */ - -/* LM80_CFG Configuration Register */ -#define LM80_CFG_START (1<<0) /* start monitoring operation */ -#define LM80_CFG_INT_ENA (1<<1) /* enables the INT# Interrupt output */ -#define LM80_CFG_INT_POL (1<<2) /* INT# pol: 0 act low, 1 act high */ -#define LM80_CFG_INT_CLR (1<<3) /* disables INT#/RST_OUT#/OS# outputs */ -#define LM80_CFG_RESET (1<<4) /* signals a reset */ -#define LM80_CFG_CHASS_CLR (1<<5) /* clears Chassis Intrusion (CI) pin */ -#define LM80_CFG_GPO (1<<6) /* drives the GPO# pin */ -#define LM80_CFG_INIT (1<<7) /* restore power on defaults */ - -/* LM80_ISRC_1 Interrupt Status Register 1 */ -/* LM80_IMSK_1 Interrupt Mask Register 1 */ -#define LM80_IS_VT0 (1<<0) /* limit exceeded for Voltage 0 */ -#define LM80_IS_VT1 (1<<1) /* limit exceeded for Voltage 1 */ -#define LM80_IS_VT2 (1<<2) /* limit exceeded for Voltage 2 */ -#define LM80_IS_VT3 (1<<3) /* limit exceeded for Voltage 3 */ -#define LM80_IS_VT4 (1<<4) /* limit exceeded for Voltage 4 */ -#define LM80_IS_VT5 (1<<5) /* limit exceeded for Voltage 5 */ -#define LM80_IS_VT6 (1<<6) /* limit exceeded for Voltage 6 */ -#define LM80_IS_INT_IN (1<<7) /* state of INT_IN# */ - -/* LM80_ISRC_2 Interrupt Status Register 2 */ -/* LM80_IMSK_2 Interrupt Mask Register 2 */ -#define LM80_IS_TEMP (1<<0) /* HOT temperature limit exceeded */ -#define LM80_IS_BTI (1<<1) /* state of BTI# pin */ -#define LM80_IS_FAN1 (1<<2) /* count limit exceeded for Fan 1 */ -#define LM80_IS_FAN2 (1<<3) /* count limit exceeded for Fan 2 */ -#define LM80_IS_CI (1<<4) /* Chassis Intrusion occured */ -#define LM80_IS_OS (1<<5) /* OS temperature limit exceeded */ - /* bit 6 and 7 are reserved in LM80_ISRC_2 */ -#define LM80_IS_HT_IRQ_MD (1<<6) /* Hot temperature interrupt mode */ -#define LM80_IS_OT_IRQ_MD (1<<7) /* OS temperature interrupt mode */ - -/* LM80_FAN_CTRL Fan Devisor/RST#/OS# Register */ -#define LM80_FAN1_MD_SEL (1<<0) /* Fan 1 mode select */ -#define LM80_FAN2_MD_SEL (1<<1) /* Fan 2 mode select */ -#define LM80_FAN1_PRM_CTL (3<<2) /* Fan 1 speed control */ -#define LM80_FAN2_PRM_CTL (3<<4) /* Fan 2 speed control */ -#define LM80_FAN_OS_ENA (1<<6) /* enable OS mode on RST_OUT#/OS# pins*/ -#define LM80_FAN_RST_ENA (1<<7) /* sets RST_OUT#/OS# pins in RST mode */ - -/* LM80_TEMP_CTRL OS# Config, Temp Res. Reg */ -#define LM80_TEMP_OS_STAT (1<<0) /* mirrors the state of RST_OUT#/OS# */ -#define LM80_TEMP_OS_POL (1<<1) /* select OS# polarity */ -#define LM80_TEMP_OS_MODE (1<<2) /* selects Interrupt mode */ -#define LM80_TEMP_RES (1<<3) /* selects 9 or 11 bit temp resulution*/ -#define LM80_TEMP_LSB (0xf<<4)/* 4 LSBs of 11 bit temp data */ -#define LM80_TEMP_LSB_9 (1<<7) /* LSB of 9 bit temperature data */ - - /* 0x07 - 0x1f reserved */ -/* LM80_VT0_IN current Voltage 0 value */ -/* LM80_VT1_IN current Voltage 1 value */ -/* LM80_VT2_IN current Voltage 2 value */ -/* LM80_VT3_IN current Voltage 3 value */ -/* LM80_VT4_IN current Voltage 4 value */ -/* LM80_VT5_IN current Voltage 5 value */ -/* LM80_VT6_IN current Voltage 6 value */ -/* LM80_TEMP_IN current temperature value */ -/* LM80_FAN1_IN current Fan 1 count */ -/* LM80_FAN2_IN current Fan 2 count */ -/* LM80_VT0_HIGH_LIM high limit val for Voltage 0 */ -/* LM80_VT0_LOW_LIM low limit val for Voltage 0 */ -/* LM80_VT1_HIGH_LIM high limit val for Voltage 1 */ -/* LM80_VT1_LOW_LIM low limit val for Voltage 1 */ -/* LM80_VT2_HIGH_LIM high limit val for Voltage 2 */ -/* LM80_VT2_LOW_LIM low limit val for Voltage 2 */ -/* LM80_VT3_HIGH_LIM high limit val for Voltage 3 */ -/* LM80_VT3_LOW_LIM low limit val for Voltage 3 */ -/* LM80_VT4_HIGH_LIM high limit val for Voltage 4 */ -/* LM80_VT4_LOW_LIM low limit val for Voltage 4 */ -/* LM80_VT5_HIGH_LIM high limit val for Voltage 5 */ -/* LM80_VT5_LOW_LIM low limit val for Voltage 5 */ -/* LM80_VT6_HIGH_LIM high limit val for Voltage 6 */ -/* LM80_VT6_LOW_LIM low limit val for Voltage 6 */ -/* LM80_THOT_LIM_UP hot temperature limit (high) */ -/* LM80_THOT_LIM_LO hot temperature limit (low) */ -/* LM80_TOS_LIM_UP OS temperature limit (high) */ -/* LM80_TOS_LIM_LO OS temperature limit (low) */ -/* LM80_FAN1_COUNT_LIM Fan 1 count limit (high) */ -/* LM80_FAN2_COUNT_LIM Fan 2 count limit (low) */ - /* 0x3e - 0x3f reserved */ - -#define LM80_ADDR 0x28 /* LM80 default addr */ - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_LM80_H */ diff --git a/drivers/net/sk98lin/h/skaddr.h b/drivers/net/sk98lin/h/skaddr.h deleted file mode 100644 index 423ad063d09b..000000000000 --- a/drivers/net/sk98lin/h/skaddr.h +++ /dev/null @@ -1,285 +0,0 @@ -/****************************************************************************** - * - * Name: skaddr.h - * Project: Gigabit Ethernet Adapters, ADDR-Modul - * Version: $Revision: 1.29 $ - * Date: $Date: 2003/05/13 16:57:24 $ - * Purpose: Header file for Address Management (MC, UC, Prom). - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module is intended to manage multicast addresses and promiscuous mode - * on GEnesis adapters. - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * ... - * "sktypes.h" - * "skqueue.h" - * "skaddr.h" - * ... - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef __INC_SKADDR_H -#define __INC_SKADDR_H - -#ifdef __cplusplus -extern "C" { -#endif /* cplusplus */ - -/* defines ********************************************************************/ - -#define SK_MAC_ADDR_LEN 6 /* Length of MAC address. */ -#define SK_MAX_ADDRS 14 /* #Addrs for exact match. */ - -/* ----- Common return values ----- */ - -#define SK_ADDR_SUCCESS 0 /* Function returned successfully. */ -#define SK_ADDR_ILLEGAL_PORT 100 /* Port number too high. */ -#define SK_ADDR_TOO_EARLY 101 /* Function called too early. */ - -/* ----- Clear/Add flag bits ----- */ - -#define SK_ADDR_PERMANENT 1 /* RLMT Address */ - -/* ----- Additional Clear flag bits ----- */ - -#define SK_MC_SW_ONLY 2 /* Do not update HW when clearing. */ - -/* ----- Override flag bits ----- */ - -#define SK_ADDR_LOGICAL_ADDRESS 0 -#define SK_ADDR_VIRTUAL_ADDRESS (SK_ADDR_LOGICAL_ADDRESS) /* old */ -#define SK_ADDR_PHYSICAL_ADDRESS 1 -#define SK_ADDR_CLEAR_LOGICAL 2 -#define SK_ADDR_SET_LOGICAL 4 - -/* ----- Override return values ----- */ - -#define SK_ADDR_OVERRIDE_SUCCESS (SK_ADDR_SUCCESS) -#define SK_ADDR_DUPLICATE_ADDRESS 1 -#define SK_ADDR_MULTICAST_ADDRESS 2 - -/* ----- Partitioning of excact match table ----- */ - -#define SK_ADDR_EXACT_MATCHES 16 /* #Exact match entries. */ - -#define SK_ADDR_FIRST_MATCH_RLMT 1 -#define SK_ADDR_LAST_MATCH_RLMT 2 -#define SK_ADDR_FIRST_MATCH_DRV 3 -#define SK_ADDR_LAST_MATCH_DRV (SK_ADDR_EXACT_MATCHES - 1) - -/* ----- SkAddrMcAdd/SkAddrMcUpdate return values ----- */ - -#define SK_MC_FILTERING_EXACT 0 /* Exact filtering. */ -#define SK_MC_FILTERING_INEXACT 1 /* Inexact filtering. */ - -/* ----- Additional SkAddrMcAdd return values ----- */ - -#define SK_MC_ILLEGAL_ADDRESS 2 /* Illegal address. */ -#define SK_MC_ILLEGAL_PORT 3 /* Illegal port (not the active one). */ -#define SK_MC_RLMT_OVERFLOW 4 /* Too many RLMT mc addresses. */ - -/* Promiscuous mode bits ----- */ - -#define SK_PROM_MODE_NONE 0 /* Normal receive. */ -#define SK_PROM_MODE_LLC 1 /* Receive all LLC frames. */ -#define SK_PROM_MODE_ALL_MC 2 /* Receive all multicast frames. */ -/* #define SK_PROM_MODE_NON_LLC 4 */ /* Receive all non-LLC frames. */ - -/* Macros */ - -#ifdef OLD_STUFF -#ifndef SK_ADDR_EQUAL -/* - * "&" instead of "&&" allows better optimization on IA-64. - * The replacement is safe here, as all bytes exist. - */ -#ifndef SK_ADDR_DWORD_COMPARE -#define SK_ADDR_EQUAL(A1,A2) ( \ - (((SK_U8 *)(A1))[5] == ((SK_U8 *)(A2))[5]) & \ - (((SK_U8 *)(A1))[4] == ((SK_U8 *)(A2))[4]) & \ - (((SK_U8 *)(A1))[3] == ((SK_U8 *)(A2))[3]) & \ - (((SK_U8 *)(A1))[2] == ((SK_U8 *)(A2))[2]) & \ - (((SK_U8 *)(A1))[1] == ((SK_U8 *)(A2))[1]) & \ - (((SK_U8 *)(A1))[0] == ((SK_U8 *)(A2))[0])) -#else /* SK_ADDR_DWORD_COMPARE */ -#define SK_ADDR_EQUAL(A1,A2) ( \ - (*(SK_U32 *)&(((SK_U8 *)(A1))[2]) == *(SK_U32 *)&(((SK_U8 *)(A2))[2])) & \ - (*(SK_U32 *)&(((SK_U8 *)(A1))[0]) == *(SK_U32 *)&(((SK_U8 *)(A2))[0]))) -#endif /* SK_ADDR_DWORD_COMPARE */ -#endif /* SK_ADDR_EQUAL */ -#endif /* 0 */ - -#ifndef SK_ADDR_EQUAL -#ifndef SK_ADDR_DWORD_COMPARE -#define SK_ADDR_EQUAL(A1,A2) ( \ - (((SK_U8 SK_FAR *)(A1))[5] == ((SK_U8 SK_FAR *)(A2))[5]) & \ - (((SK_U8 SK_FAR *)(A1))[4] == ((SK_U8 SK_FAR *)(A2))[4]) & \ - (((SK_U8 SK_FAR *)(A1))[3] == ((SK_U8 SK_FAR *)(A2))[3]) & \ - (((SK_U8 SK_FAR *)(A1))[2] == ((SK_U8 SK_FAR *)(A2))[2]) & \ - (((SK_U8 SK_FAR *)(A1))[1] == ((SK_U8 SK_FAR *)(A2))[1]) & \ - (((SK_U8 SK_FAR *)(A1))[0] == ((SK_U8 SK_FAR *)(A2))[0])) -#else /* SK_ADDR_DWORD_COMPARE */ -#define SK_ADDR_EQUAL(A1,A2) ( \ - (*(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[4]) == \ - *(SK_U16 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[4])) && \ - (*(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A1))[0]) == \ - *(SK_U32 SK_FAR *)&(((SK_U8 SK_FAR *)(A2))[0]))) -#endif /* SK_ADDR_DWORD_COMPARE */ -#endif /* SK_ADDR_EQUAL */ - -/* typedefs *******************************************************************/ - -typedef struct s_MacAddr { - SK_U8 a[SK_MAC_ADDR_LEN]; -} SK_MAC_ADDR; - - -/* SK_FILTER is used to ensure alignment of the filter. */ -typedef union s_InexactFilter { - SK_U8 Bytes[8]; - SK_U64 Val; /* Dummy entry for alignment only. */ -} SK_FILTER64; - - -typedef struct s_AddrNet SK_ADDR_NET; - - -typedef struct s_AddrPort { - -/* ----- Public part (read-only) ----- */ - - SK_MAC_ADDR CurrentMacAddress; /* Current physical MAC Address. */ - SK_MAC_ADDR PermanentMacAddress; /* Permanent physical MAC Address. */ - int PromMode; /* Promiscuous Mode. */ - -/* ----- Private part ----- */ - - SK_MAC_ADDR PreviousMacAddress; /* Prev. phys. MAC Address. */ - SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */ - SK_U8 Align01; - - SK_U32 FirstExactMatchRlmt; - SK_U32 NextExactMatchRlmt; - SK_U32 FirstExactMatchDrv; - SK_U32 NextExactMatchDrv; - SK_MAC_ADDR Exact[SK_ADDR_EXACT_MATCHES]; - SK_FILTER64 InexactFilter; /* For 64-bit hash register. */ - SK_FILTER64 InexactRlmtFilter; /* For 64-bit hash register. */ - SK_FILTER64 InexactDrvFilter; /* For 64-bit hash register. */ -} SK_ADDR_PORT; - - -struct s_AddrNet { -/* ----- Public part (read-only) ----- */ - - SK_MAC_ADDR CurrentMacAddress; /* Logical MAC Address. */ - SK_MAC_ADDR PermanentMacAddress; /* Logical MAC Address. */ - -/* ----- Private part ----- */ - - SK_U32 ActivePort; /* View of module ADDR. */ - SK_BOOL CurrentMacAddressSet; /* CurrentMacAddress is set. */ - SK_U8 Align01; - SK_U16 Align02; -}; - - -typedef struct s_Addr { - -/* ----- Public part (read-only) ----- */ - - SK_ADDR_NET Net[SK_MAX_NETS]; - SK_ADDR_PORT Port[SK_MAX_MACS]; - -/* ----- Private part ----- */ -} SK_ADDR; - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO - -/* Functions provided by SkAddr */ - -/* ANSI/C++ compliant function prototypes */ - -extern int SkAddrInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern int SkAddrMcClear( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int Flags); - -extern int SkAddrMcAdd( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR *pMc, - int Flags); - -extern int SkAddrMcUpdate( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber); - -extern int SkAddrOverride( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - SK_MAC_ADDR SK_FAR *pNewAddr, - int Flags); - -extern int SkAddrPromiscuousChange( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 PortNumber, - int NewPromMode); - -#ifndef SK_SLIM -extern int SkAddrSwap( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 FromPortNumber, - SK_U32 ToPortNumber); -#endif - -#else /* defined(SK_KR_PROTO)) */ - -/* Non-ANSI/C++ compliant function prototypes */ - -#error KR-style prototypes are not yet provided. - -#endif /* defined(SK_KR_PROTO)) */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKADDR_H */ diff --git a/drivers/net/sk98lin/h/skcsum.h b/drivers/net/sk98lin/h/skcsum.h deleted file mode 100644 index 6e256bd9a28c..000000000000 --- a/drivers/net/sk98lin/h/skcsum.h +++ /dev/null @@ -1,213 +0,0 @@ -/****************************************************************************** - * - * Name: skcsum.h - * Project: GEnesis - SysKonnect SK-NET Gigabit Ethernet (SK-98xx) - * Version: $Revision: 1.10 $ - * Date: $Date: 2003/08/20 13:59:57 $ - * Purpose: Store/verify Internet checksum in send/receive packets. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2001 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * Public header file for the "GEnesis" common module "CSUM". - * - * "GEnesis" is an abbreviation of "Gigabit Ethernet Network System in Silicon" - * and is the code name of this SysKonnect project. - * - * Compilation Options: - * - * SK_USE_CSUM - Define if CSUM is to be used. Otherwise, CSUM will be an - * empty module. - * - * SKCS_OVERWRITE_PROTO - Define to overwrite the default protocol id - * definitions. In this case, all SKCS_PROTO_xxx definitions must be made - * external. - * - * SKCS_OVERWRITE_STATUS - Define to overwrite the default return status - * definitions. In this case, all SKCS_STATUS_xxx definitions must be made - * external. - * - * Include File Hierarchy: - * - * "h/skcsum.h" - * "h/sktypes.h" - * "h/skqueue.h" - * - ******************************************************************************/ - -#ifndef __INC_SKCSUM_H -#define __INC_SKCSUM_H - -#include "h/sktypes.h" -#include "h/skqueue.h" - -/* defines ********************************************************************/ - -/* - * Define the default bit flags for 'SKCS_PACKET_INFO.ProtocolFlags' if no user - * overwrite. - */ -#ifndef SKCS_OVERWRITE_PROTO /* User overwrite? */ -#define SKCS_PROTO_IP 0x1 /* IP (Internet Protocol version 4) */ -#define SKCS_PROTO_TCP 0x2 /* TCP (Transmission Control Protocol) */ -#define SKCS_PROTO_UDP 0x4 /* UDP (User Datagram Protocol) */ - -/* Indices for protocol statistics. */ -#define SKCS_PROTO_STATS_IP 0 -#define SKCS_PROTO_STATS_UDP 1 -#define SKCS_PROTO_STATS_TCP 2 -#define SKCS_NUM_PROTOCOLS 3 /* Number of supported protocols. */ -#endif /* !SKCS_OVERWRITE_PROTO */ - -/* - * Define the default SKCS_STATUS type and values if no user overwrite. - * - * SKCS_STATUS_UNKNOWN_IP_VERSION - Not an IP v4 frame. - * SKCS_STATUS_IP_CSUM_ERROR - IP checksum error. - * SKCS_STATUS_IP_CSUM_ERROR_TCP - IP checksum error in TCP frame. - * SKCS_STATUS_IP_CSUM_ERROR_UDP - IP checksum error in UDP frame - * SKCS_STATUS_IP_FRAGMENT - IP fragment (IP checksum ok). - * SKCS_STATUS_IP_CSUM_OK - IP checksum ok (not a TCP or UDP frame). - * SKCS_STATUS_TCP_CSUM_ERROR - TCP checksum error (IP checksum ok). - * SKCS_STATUS_UDP_CSUM_ERROR - UDP checksum error (IP checksum ok). - * SKCS_STATUS_TCP_CSUM_OK - IP and TCP checksum ok. - * SKCS_STATUS_UDP_CSUM_OK - IP and UDP checksum ok. - * SKCS_STATUS_IP_CSUM_OK_NO_UDP - IP checksum OK and no UDP checksum. - */ -#ifndef SKCS_OVERWRITE_STATUS /* User overwrite? */ -#define SKCS_STATUS int /* Define status type. */ - -#define SKCS_STATUS_UNKNOWN_IP_VERSION 1 -#define SKCS_STATUS_IP_CSUM_ERROR 2 -#define SKCS_STATUS_IP_FRAGMENT 3 -#define SKCS_STATUS_IP_CSUM_OK 4 -#define SKCS_STATUS_TCP_CSUM_ERROR 5 -#define SKCS_STATUS_UDP_CSUM_ERROR 6 -#define SKCS_STATUS_TCP_CSUM_OK 7 -#define SKCS_STATUS_UDP_CSUM_OK 8 -/* needed for Microsoft */ -#define SKCS_STATUS_IP_CSUM_ERROR_UDP 9 -#define SKCS_STATUS_IP_CSUM_ERROR_TCP 10 -/* UDP checksum may be omitted */ -#define SKCS_STATUS_IP_CSUM_OK_NO_UDP 11 -#endif /* !SKCS_OVERWRITE_STATUS */ - -/* Clear protocol statistics event. */ -#define SK_CSUM_EVENT_CLEAR_PROTO_STATS 1 - -/* - * Add two values in one's complement. - * - * Note: One of the two input values may be "longer" than 16-bit, but then the - * resulting sum may be 17 bits long. In this case, add zero to the result using - * SKCS_OC_ADD() again. - * - * Result = Value1 + Value2 - */ -#define SKCS_OC_ADD(Result, Value1, Value2) { \ - unsigned long Sum; \ - \ - Sum = (unsigned long) (Value1) + (unsigned long) (Value2); \ - /* Add-in any carry. */ \ - (Result) = (Sum & 0xffff) + (Sum >> 16); \ -} - -/* - * Subtract two values in one's complement. - * - * Result = Value1 - Value2 - */ -#define SKCS_OC_SUB(Result, Value1, Value2) \ - SKCS_OC_ADD((Result), (Value1), ~(Value2) & 0xffff) - -/* typedefs *******************************************************************/ - -/* - * SKCS_PROTO_STATS - The CSUM protocol statistics structure. - * - * There is one instance of this structure for each protocol supported. - */ -typedef struct s_CsProtocolStatistics { - SK_U64 RxOkCts; /* Receive checksum ok. */ - SK_U64 RxUnableCts; /* Unable to verify receive checksum. */ - SK_U64 RxErrCts; /* Receive checksum error. */ - SK_U64 TxOkCts; /* Transmit checksum ok. */ - SK_U64 TxUnableCts; /* Unable to calculate checksum in hw. */ -} SKCS_PROTO_STATS; - -/* - * s_Csum - The CSUM module context structure. - */ -typedef struct s_Csum { - /* Enabled receive SK_PROTO_XXX bit flags. */ - unsigned ReceiveFlags[SK_MAX_NETS]; -#ifdef TX_CSUM - unsigned TransmitFlags[SK_MAX_NETS]; -#endif /* TX_CSUM */ - - /* The protocol statistics structure; one per supported protocol. */ - SKCS_PROTO_STATS ProtoStats[SK_MAX_NETS][SKCS_NUM_PROTOCOLS]; -} SK_CSUM; - -/* - * SKCS_PACKET_INFO - The packet information structure. - */ -typedef struct s_CsPacketInfo { - /* Bit field specifiying the desired/found protocols. */ - unsigned ProtocolFlags; - - /* Length of complete IP header, including any option fields. */ - unsigned IpHeaderLength; - - /* IP header checksum. */ - unsigned IpHeaderChecksum; - - /* TCP/UDP pseudo header checksum. */ - unsigned PseudoHeaderChecksum; -} SKCS_PACKET_INFO; - -/* function prototypes ********************************************************/ - -#ifndef SK_CS_CALCULATE_CHECKSUM -extern unsigned SkCsCalculateChecksum( - void *pData, - unsigned Length); -#endif /* SK_CS_CALCULATE_CHECKSUM */ - -extern int SkCsEvent( - SK_AC *pAc, - SK_IOC Ioc, - SK_U32 Event, - SK_EVPARA Param); - -extern SKCS_STATUS SkCsGetReceiveInfo( - SK_AC *pAc, - void *pIpHeader, - unsigned Checksum1, - unsigned Checksum2, - int NetNumber); - -extern void SkCsSetReceiveFlags( - SK_AC *pAc, - unsigned ReceiveFlags, - unsigned *pChecksum1Offset, - unsigned *pChecksum2Offset, - int NetNumber); - -#endif /* __INC_SKCSUM_H */ diff --git a/drivers/net/sk98lin/h/skdebug.h b/drivers/net/sk98lin/h/skdebug.h deleted file mode 100644 index 3cba171d74b2..000000000000 --- a/drivers/net/sk98lin/h/skdebug.h +++ /dev/null @@ -1,74 +0,0 @@ -/****************************************************************************** - * - * Name: skdebug.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.14 $ - * Date: $Date: 2003/05/13 17:26:00 $ - * Purpose: SK specific DEBUG support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_SKDEBUG_H -#define __INC_SKDEBUG_H - -#ifdef DEBUG -#ifndef SK_DBG_MSG -#define SK_DBG_MSG(pAC,comp,cat,arg) \ - if ( ((comp) & SK_DBG_CHKMOD(pAC)) && \ - ((cat) & SK_DBG_CHKCAT(pAC)) ) { \ - SK_DBG_PRINTF arg ; \ - } -#endif -#else -#define SK_DBG_MSG(pAC,comp,lev,arg) -#endif - -/* PLS NOTE: - * ========= - * Due to any restrictions of kernel printf routines do not use other - * format identifiers as: %x %d %c %s . - * Never use any combined format identifiers such as: %lx %ld in your - * printf - argument (arg) because some OS specific kernel printfs may - * only support some basic identifiers. - */ - -/* Debug modules */ - -#define SK_DBGMOD_MERR 0x00000001L /* general module error indication */ -#define SK_DBGMOD_HWM 0x00000002L /* Hardware init module */ -#define SK_DBGMOD_RLMT 0x00000004L /* RLMT module */ -#define SK_DBGMOD_VPD 0x00000008L /* VPD module */ -#define SK_DBGMOD_I2C 0x00000010L /* I2C module */ -#define SK_DBGMOD_PNMI 0x00000020L /* PNMI module */ -#define SK_DBGMOD_CSUM 0x00000040L /* CSUM module */ -#define SK_DBGMOD_ADDR 0x00000080L /* ADDR module */ -#define SK_DBGMOD_PECP 0x00000100L /* PECP module */ -#define SK_DBGMOD_POWM 0x00000200L /* Power Management module */ - -/* Debug events */ - -#define SK_DBGCAT_INIT 0x00000001L /* module/driver initialization */ -#define SK_DBGCAT_CTRL 0x00000002L /* controlling devices */ -#define SK_DBGCAT_ERR 0x00000004L /* error handling paths */ -#define SK_DBGCAT_TX 0x00000008L /* transmit path */ -#define SK_DBGCAT_RX 0x00000010L /* receive path */ -#define SK_DBGCAT_IRQ 0x00000020L /* general IRQ handling */ -#define SK_DBGCAT_QUEUE 0x00000040L /* any queue management */ -#define SK_DBGCAT_DUMP 0x00000080L /* large data output e.g. hex dump */ -#define SK_DBGCAT_FATAL 0x00000100L /* fatal error */ - -#endif /* __INC_SKDEBUG_H */ diff --git a/drivers/net/sk98lin/h/skdrv1st.h b/drivers/net/sk98lin/h/skdrv1st.h deleted file mode 100644 index 91b8d4f45904..000000000000 --- a/drivers/net/sk98lin/h/skdrv1st.h +++ /dev/null @@ -1,188 +0,0 @@ -/****************************************************************************** - * - * Name: skdrv1st.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.4 $ - * Date: $Date: 2003/11/12 14:28:14 $ - * Purpose: First header file for driver and all other modules - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the first include file of the driver, which includes all - * neccessary system header files and some of the GEnesis header files. - * It also defines some basic items. - * - * Include File Hierarchy: - * - * see skge.c - * - ******************************************************************************/ - -#ifndef __INC_SKDRV1ST_H -#define __INC_SKDRV1ST_H - -typedef struct s_AC SK_AC; - -/* Set card versions */ -#define SK_FAR - -/* override some default functions with optimized linux functions */ - -#define SK_PNMI_STORE_U16(p,v) memcpy((char*)(p),(char*)&(v),2) -#define SK_PNMI_STORE_U32(p,v) memcpy((char*)(p),(char*)&(v),4) -#define SK_PNMI_STORE_U64(p,v) memcpy((char*)(p),(char*)&(v),8) -#define SK_PNMI_READ_U16(p,v) memcpy((char*)&(v),(char*)(p),2) -#define SK_PNMI_READ_U32(p,v) memcpy((char*)&(v),(char*)(p),4) -#define SK_PNMI_READ_U64(p,v) memcpy((char*)&(v),(char*)(p),8) - -#define SK_ADDR_EQUAL(a1,a2) (!memcmp(a1,a2,6)) - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#define SK_CS_CALCULATE_CHECKSUM -#ifndef CONFIG_X86_64 -#define SkCsCalculateChecksum(p,l) ((~ip_compute_csum(p, l)) & 0xffff) -#else -#define SkCsCalculateChecksum(p,l) ((~ip_fast_csum(p, l)) & 0xffff) -#endif - -#include "h/sktypes.h" -#include "h/skerror.h" -#include "h/skdebug.h" -#include "h/lm80.h" -#include "h/xmac_ii.h" - -#ifdef __LITTLE_ENDIAN -#define SK_LITTLE_ENDIAN -#else -#define SK_BIG_ENDIAN -#endif - -#define SK_NET_DEVICE net_device - - -/* we use gethrtime(), return unit: nanoseconds */ -#define SK_TICKS_PER_SEC 100 - -#define SK_MEM_MAPPED_IO - -// #define SK_RLMT_SLOW_LOOKAHEAD - -#define SK_MAX_MACS 2 -#define SK_MAX_NETS 2 - -#define SK_IOC char __iomem * - -typedef struct s_DrvRlmtMbuf SK_MBUF; - -#define SK_CONST64 INT64_C -#define SK_CONSTU64 UINT64_C - -#define SK_MEMCPY(dest,src,size) memcpy(dest,src,size) -#define SK_MEMCMP(s1,s2,size) memcmp(s1,s2,size) -#define SK_MEMSET(dest,val,size) memset(dest,val,size) -#define SK_STRLEN(pStr) strlen((char*)(pStr)) -#define SK_STRNCPY(pDest,pSrc,size) strncpy((char*)(pDest),(char*)(pSrc),size) -#define SK_STRCMP(pStr1,pStr2) strcmp((char*)(pStr1),(char*)(pStr2)) - -/* macros to access the adapter */ -#define SK_OUT8(b,a,v) writeb((v), ((b)+(a))) -#define SK_OUT16(b,a,v) writew((v), ((b)+(a))) -#define SK_OUT32(b,a,v) writel((v), ((b)+(a))) -#define SK_IN8(b,a,pv) (*(pv) = readb((b)+(a))) -#define SK_IN16(b,a,pv) (*(pv) = readw((b)+(a))) -#define SK_IN32(b,a,pv) (*(pv) = readl((b)+(a))) - -#define int8_t char -#define int16_t short -#define int32_t long -#define int64_t long long -#define uint8_t u_char -#define uint16_t u_short -#define uint32_t u_long -#define uint64_t unsigned long long -#define t_scalar_t int -#define t_uscalar_t unsigned int -#define uintptr_t unsigned long - -#define __CONCAT__(A,B) A##B - -#define INT32_C(a) __CONCAT__(a,L) -#define INT64_C(a) __CONCAT__(a,LL) -#define UINT32_C(a) __CONCAT__(a,UL) -#define UINT64_C(a) __CONCAT__(a,ULL) - -#ifdef DEBUG -#define SK_DBG_PRINTF printk -#ifndef SK_DEBUG_CHKMOD -#define SK_DEBUG_CHKMOD 0 -#endif -#ifndef SK_DEBUG_CHKCAT -#define SK_DEBUG_CHKCAT 0 -#endif -/* those come from the makefile */ -#define SK_DBG_CHKMOD(pAC) (SK_DEBUG_CHKMOD) -#define SK_DBG_CHKCAT(pAC) (SK_DEBUG_CHKCAT) - -extern void SkDbgPrintf(const char *format,...); - -#define SK_DBGMOD_DRV 0x00010000 - -/**** possible driver debug categories ********************************/ -#define SK_DBGCAT_DRV_ENTRY 0x00010000 -#define SK_DBGCAT_DRV_SAP 0x00020000 -#define SK_DBGCAT_DRV_MCA 0x00040000 -#define SK_DBGCAT_DRV_TX_PROGRESS 0x00080000 -#define SK_DBGCAT_DRV_RX_PROGRESS 0x00100000 -#define SK_DBGCAT_DRV_PROGRESS 0x00200000 -#define SK_DBGCAT_DRV_MSG 0x00400000 -#define SK_DBGCAT_DRV_PROM 0x00800000 -#define SK_DBGCAT_DRV_TX_FRAME 0x01000000 -#define SK_DBGCAT_DRV_ERROR 0x02000000 -#define SK_DBGCAT_DRV_INT_SRC 0x04000000 -#define SK_DBGCAT_DRV_EVENT 0x08000000 - -#endif - -#define SK_ERR_LOG SkErrorLog - -extern void SkErrorLog(SK_AC*, int, int, char*); - -#endif - diff --git a/drivers/net/sk98lin/h/skdrv2nd.h b/drivers/net/sk98lin/h/skdrv2nd.h deleted file mode 100644 index 3fa67171e832..000000000000 --- a/drivers/net/sk98lin/h/skdrv2nd.h +++ /dev/null @@ -1,447 +0,0 @@ -/****************************************************************************** - * - * Name: skdrv2nd.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.10 $ - * Date: $Date: 2003/12/11 16:04:45 $ - * Purpose: Second header file for driver and all other modules - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the second include file of the driver, which includes all other - * neccessary files and defines all structures and constants used by the - * driver and the common modules. - * - * Include File Hierarchy: - * - * see skge.c - * - ******************************************************************************/ - -#ifndef __INC_SKDRV2ND_H -#define __INC_SKDRV2ND_H - -#include "h/skqueue.h" -#include "h/skgehwt.h" -#include "h/sktimer.h" -#include "h/ski2c.h" -#include "h/skgepnmi.h" -#include "h/skvpd.h" -#include "h/skgehw.h" -#include "h/skgeinit.h" -#include "h/skaddr.h" -#include "h/skgesirq.h" -#include "h/skcsum.h" -#include "h/skrlmt.h" -#include "h/skgedrv.h" - - -extern SK_MBUF *SkDrvAllocRlmtMbuf(SK_AC*, SK_IOC, unsigned); -extern void SkDrvFreeRlmtMbuf(SK_AC*, SK_IOC, SK_MBUF*); -extern SK_U64 SkOsGetTime(SK_AC*); -extern int SkPciReadCfgDWord(SK_AC*, int, SK_U32*); -extern int SkPciReadCfgWord(SK_AC*, int, SK_U16*); -extern int SkPciReadCfgByte(SK_AC*, int, SK_U8*); -extern int SkPciWriteCfgWord(SK_AC*, int, SK_U16); -extern int SkPciWriteCfgByte(SK_AC*, int, SK_U8); -extern int SkDrvEvent(SK_AC*, SK_IOC IoC, SK_U32, SK_EVPARA); - -#ifdef SK_DIAG_SUPPORT -extern int SkDrvEnterDiagMode(SK_AC *pAc); -extern int SkDrvLeaveDiagMode(SK_AC *pAc); -#endif - -struct s_DrvRlmtMbuf { - SK_MBUF *pNext; /* Pointer to next RLMT Mbuf. */ - SK_U8 *pData; /* Data buffer (virtually contig.). */ - unsigned Size; /* Data buffer size. */ - unsigned Length; /* Length of packet (<= Size). */ - SK_U32 PortIdx; /* Receiving/transmitting port. */ -#ifdef SK_RLMT_MBUF_PRIVATE - SK_RLMT_MBUF Rlmt; /* Private part for RLMT. */ -#endif /* SK_RLMT_MBUF_PRIVATE */ - struct sk_buff *pOs; /* Pointer to message block */ -}; - - -/* - * Time macros - */ -#if SK_TICKS_PER_SEC == 100 -#define SK_PNMI_HUNDREDS_SEC(t) (t) -#else -#define SK_PNMI_HUNDREDS_SEC(t) ((((unsigned long)t) * 100) / \ - (SK_TICKS_PER_SEC)) -#endif - -/* - * New SkOsGetTime - */ -#define SkOsGetTimeCurrent(pAC, pUsec) {\ - struct timeval t;\ - do_gettimeofday(&t);\ - *pUsec = ((((t.tv_sec) * 1000000L)+t.tv_usec)/10000);\ -} - - -/* - * ioctl definitions - */ -#define SK_IOCTL_BASE (SIOCDEVPRIVATE) -#define SK_IOCTL_GETMIB (SK_IOCTL_BASE + 0) -#define SK_IOCTL_SETMIB (SK_IOCTL_BASE + 1) -#define SK_IOCTL_PRESETMIB (SK_IOCTL_BASE + 2) -#define SK_IOCTL_GEN (SK_IOCTL_BASE + 3) -#define SK_IOCTL_DIAG (SK_IOCTL_BASE + 4) - -typedef struct s_IOCTL SK_GE_IOCTL; - -struct s_IOCTL { - char __user * pData; - unsigned int Len; -}; - - -/* - * define sizes of descriptor rings in bytes - */ - -#define TX_RING_SIZE (8*1024) -#define RX_RING_SIZE (24*1024) - -/* - * Buffer size for ethernet packets - */ -#define ETH_BUF_SIZE 1540 -#define ETH_MAX_MTU 1514 -#define ETH_MIN_MTU 60 -#define ETH_MULTICAST_BIT 0x01 -#define SK_JUMBO_MTU 9000 - -/* - * transmit priority selects the queue: LOW=asynchron, HIGH=synchron - */ -#define TX_PRIO_LOW 0 -#define TX_PRIO_HIGH 1 - -/* - * alignment of rx/tx descriptors - */ -#define DESCR_ALIGN 64 - -/* - * definitions for pnmi. TODO - */ -#define SK_DRIVER_RESET(pAC, IoC) 0 -#define SK_DRIVER_SENDEVENT(pAC, IoC) 0 -#define SK_DRIVER_SELFTEST(pAC, IoC) 0 -/* For get mtu you must add an own function */ -#define SK_DRIVER_GET_MTU(pAc,IoC,i) 0 -#define SK_DRIVER_SET_MTU(pAc,IoC,i,v) 0 -#define SK_DRIVER_PRESET_MTU(pAc,IoC,i,v) 0 - -/* -** Interim definition of SK_DRV_TIMER placed in this file until -** common modules have been finalized -*/ -#define SK_DRV_TIMER 11 -#define SK_DRV_MODERATION_TIMER 1 -#define SK_DRV_MODERATION_TIMER_LENGTH 1000000 /* 1 second */ -#define SK_DRV_RX_CLEANUP_TIMER 2 -#define SK_DRV_RX_CLEANUP_TIMER_LENGTH 1000000 /* 100 millisecs */ - -/* -** Definitions regarding transmitting frames -** any calculating any checksum. -*/ -#define C_LEN_ETHERMAC_HEADER_DEST_ADDR 6 -#define C_LEN_ETHERMAC_HEADER_SRC_ADDR 6 -#define C_LEN_ETHERMAC_HEADER_LENTYPE 2 -#define C_LEN_ETHERMAC_HEADER ( (C_LEN_ETHERMAC_HEADER_DEST_ADDR) + \ - (C_LEN_ETHERMAC_HEADER_SRC_ADDR) + \ - (C_LEN_ETHERMAC_HEADER_LENTYPE) ) - -#define C_LEN_ETHERMTU_MINSIZE 46 -#define C_LEN_ETHERMTU_MAXSIZE_STD 1500 -#define C_LEN_ETHERMTU_MAXSIZE_JUMBO 9000 - -#define C_LEN_ETHERNET_MINSIZE ( (C_LEN_ETHERMAC_HEADER) + \ - (C_LEN_ETHERMTU_MINSIZE) ) - -#define C_OFFSET_IPHEADER C_LEN_ETHERMAC_HEADER -#define C_OFFSET_IPHEADER_IPPROTO 9 -#define C_OFFSET_TCPHEADER_TCPCS 16 -#define C_OFFSET_UDPHEADER_UDPCS 6 - -#define C_OFFSET_IPPROTO ( (C_LEN_ETHERMAC_HEADER) + \ - (C_OFFSET_IPHEADER_IPPROTO) ) - -#define C_PROTO_ID_UDP 17 /* refer to RFC 790 or Stevens' */ -#define C_PROTO_ID_TCP 6 /* TCP/IP illustrated for details */ - -/* TX and RX descriptors *****************************************************/ - -typedef struct s_RxD RXD; /* the receive descriptor */ - -struct s_RxD { - volatile SK_U32 RBControl; /* Receive Buffer Control */ - SK_U32 VNextRxd; /* Next receive descriptor,low dword */ - SK_U32 VDataLow; /* Receive buffer Addr, low dword */ - SK_U32 VDataHigh; /* Receive buffer Addr, high dword */ - SK_U32 FrameStat; /* Receive Frame Status word */ - SK_U32 TimeStamp; /* Time stamp from XMAC */ - SK_U32 TcpSums; /* TCP Sum 2 / TCP Sum 1 */ - SK_U32 TcpSumStarts; /* TCP Sum Start 2 / TCP Sum Start 1 */ - RXD *pNextRxd; /* Pointer to next Rxd */ - struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ -}; - -typedef struct s_TxD TXD; /* the transmit descriptor */ - -struct s_TxD { - volatile SK_U32 TBControl; /* Transmit Buffer Control */ - SK_U32 VNextTxd; /* Next transmit descriptor,low dword */ - SK_U32 VDataLow; /* Transmit Buffer Addr, low dword */ - SK_U32 VDataHigh; /* Transmit Buffer Addr, high dword */ - SK_U32 FrameStat; /* Transmit Frame Status Word */ - SK_U32 TcpSumOfs; /* Reserved / TCP Sum Offset */ - SK_U16 TcpSumSt; /* TCP Sum Start */ - SK_U16 TcpSumWr; /* TCP Sum Write */ - SK_U32 TcpReserved; /* not used */ - TXD *pNextTxd; /* Pointer to next Txd */ - struct sk_buff *pMBuf; /* Pointer to Linux' socket buffer */ -}; - -/* Used interrupt bits in the interrupts source register *********************/ - -#define DRIVER_IRQS ((IS_IRQ_SW) | \ - (IS_R1_F) |(IS_R2_F) | \ - (IS_XS1_F) |(IS_XA1_F) | \ - (IS_XS2_F) |(IS_XA2_F)) - -#define SPECIAL_IRQS ((IS_HW_ERR) |(IS_I2C_READY) | \ - (IS_EXT_REG) |(IS_TIMINT) | \ - (IS_PA_TO_RX1) |(IS_PA_TO_RX2) | \ - (IS_PA_TO_TX1) |(IS_PA_TO_TX2) | \ - (IS_MAC1) |(IS_LNK_SYNC_M1)| \ - (IS_MAC2) |(IS_LNK_SYNC_M2)| \ - (IS_R1_C) |(IS_R2_C) | \ - (IS_XS1_C) |(IS_XA1_C) | \ - (IS_XS2_C) |(IS_XA2_C)) - -#define IRQ_MASK ((IS_IRQ_SW) | \ - (IS_R1_B) |(IS_R1_F) |(IS_R2_B) |(IS_R2_F) | \ - (IS_XS1_B) |(IS_XS1_F) |(IS_XA1_B)|(IS_XA1_F)| \ - (IS_XS2_B) |(IS_XS2_F) |(IS_XA2_B)|(IS_XA2_F)| \ - (IS_HW_ERR) |(IS_I2C_READY)| \ - (IS_EXT_REG) |(IS_TIMINT) | \ - (IS_PA_TO_RX1) |(IS_PA_TO_RX2)| \ - (IS_PA_TO_TX1) |(IS_PA_TO_TX2)| \ - (IS_MAC1) |(IS_MAC2) | \ - (IS_R1_C) |(IS_R2_C) | \ - (IS_XS1_C) |(IS_XA1_C) | \ - (IS_XS2_C) |(IS_XA2_C)) - -#define IRQ_HWE_MASK (IS_ERR_MSK) /* enable all HW irqs */ - -typedef struct s_DevNet DEV_NET; - -struct s_DevNet { - int PortNr; - int NetNr; - SK_AC *pAC; -}; - -typedef struct s_TxPort TX_PORT; - -struct s_TxPort { - /* the transmit descriptor rings */ - caddr_t pTxDescrRing; /* descriptor area memory */ - SK_U64 VTxDescrRing; /* descr. area bus virt. addr. */ - TXD *pTxdRingHead; /* Head of Tx rings */ - TXD *pTxdRingTail; /* Tail of Tx rings */ - TXD *pTxdRingPrev; /* descriptor sent previously */ - int TxdRingFree; /* # of free entrys */ - spinlock_t TxDesRingLock; /* serialize descriptor accesses */ - SK_IOC HwAddr; /* bmu registers address */ - int PortIndex; /* index number of port (0 or 1) */ -}; - -typedef struct s_RxPort RX_PORT; - -struct s_RxPort { - /* the receive descriptor rings */ - caddr_t pRxDescrRing; /* descriptor area memory */ - SK_U64 VRxDescrRing; /* descr. area bus virt. addr. */ - RXD *pRxdRingHead; /* Head of Rx rings */ - RXD *pRxdRingTail; /* Tail of Rx rings */ - RXD *pRxdRingPrev; /* descriptor given to BMU previously */ - int RxdRingFree; /* # of free entrys */ - int RxCsum; /* use receive checksum hardware */ - spinlock_t RxDesRingLock; /* serialize descriptor accesses */ - int RxFillLimit; /* limit for buffers in ring */ - SK_IOC HwAddr; /* bmu registers address */ - int PortIndex; /* index number of port (0 or 1) */ -}; - -/* Definitions needed for interrupt moderation *******************************/ - -#define IRQ_EOF_AS_TX ((IS_XA1_F) | (IS_XA2_F)) -#define IRQ_EOF_SY_TX ((IS_XS1_F) | (IS_XS2_F)) -#define IRQ_MASK_TX_ONLY ((IRQ_EOF_AS_TX)| (IRQ_EOF_SY_TX)) -#define IRQ_MASK_RX_ONLY ((IS_R1_F) | (IS_R2_F)) -#define IRQ_MASK_SP_ONLY (SPECIAL_IRQS) -#define IRQ_MASK_TX_RX ((IRQ_MASK_TX_ONLY)| (IRQ_MASK_RX_ONLY)) -#define IRQ_MASK_SP_RX ((SPECIAL_IRQS) | (IRQ_MASK_RX_ONLY)) -#define IRQ_MASK_SP_TX ((SPECIAL_IRQS) | (IRQ_MASK_TX_ONLY)) -#define IRQ_MASK_RX_TX_SP ((SPECIAL_IRQS) | (IRQ_MASK_TX_RX)) - -#define C_INT_MOD_NONE 1 -#define C_INT_MOD_STATIC 2 -#define C_INT_MOD_DYNAMIC 4 - -#define C_CLK_FREQ_GENESIS 53215000 /* shorter: 53.125 MHz */ -#define C_CLK_FREQ_YUKON 78215000 /* shorter: 78.125 MHz */ - -#define C_INTS_PER_SEC_DEFAULT 2000 -#define C_INT_MOD_ENABLE_PERCENTAGE 50 /* if higher 50% enable */ -#define C_INT_MOD_DISABLE_PERCENTAGE 50 /* if lower 50% disable */ -#define C_INT_MOD_IPS_LOWER_RANGE 30 -#define C_INT_MOD_IPS_UPPER_RANGE 40000 - - -typedef struct s_DynIrqModInfo DIM_INFO; -struct s_DynIrqModInfo { - unsigned long PrevTimeVal; - unsigned int PrevSysLoad; - unsigned int PrevUsedTime; - unsigned int PrevTotalTime; - int PrevUsedDescrRatio; - int NbrProcessedDescr; - SK_U64 PrevPort0RxIntrCts; - SK_U64 PrevPort1RxIntrCts; - SK_U64 PrevPort0TxIntrCts; - SK_U64 PrevPort1TxIntrCts; - SK_BOOL ModJustEnabled; /* Moderation just enabled yes/no */ - - int MaxModIntsPerSec; /* Moderation Threshold */ - int MaxModIntsPerSecUpperLimit; /* Upper limit for DIM */ - int MaxModIntsPerSecLowerLimit; /* Lower limit for DIM */ - - long MaskIrqModeration; /* ModIrqType (eg. 'TxRx') */ - SK_BOOL DisplayStats; /* Stats yes/no */ - SK_BOOL AutoSizing; /* Resize DIM-timer on/off */ - int IntModTypeSelect; /* EnableIntMod (eg. 'dynamic') */ - - SK_TIMER ModTimer; /* just some timer */ -}; - -typedef struct s_PerStrm PER_STRM; - -#define SK_ALLOC_IRQ 0x00000001 - -#ifdef SK_DIAG_SUPPORT -#define DIAG_ACTIVE 1 -#define DIAG_NOTACTIVE 0 -#endif - -/**************************************************************************** - * Per board structure / Adapter Context structure: - * Allocated within attach(9e) and freed within detach(9e). - * Contains all 'per device' necessary handles, flags, locks etc.: - */ -struct s_AC { - SK_GEINIT GIni; /* GE init struct */ - SK_PNMI Pnmi; /* PNMI data struct */ - SK_VPD vpd; /* vpd data struct */ - SK_QUEUE Event; /* Event queue */ - SK_HWT Hwt; /* Hardware Timer control struct */ - SK_TIMCTRL Tim; /* Software Timer control struct */ - SK_I2C I2c; /* I2C relevant data structure */ - SK_ADDR Addr; /* for Address module */ - SK_CSUM Csum; /* for checksum module */ - SK_RLMT Rlmt; /* for rlmt module */ - spinlock_t SlowPathLock; /* Normal IRQ lock */ - struct timer_list BlinkTimer; /* for LED blinking */ - int LedsOn; - SK_PNMI_STRUCT_DATA PnmiStruct; /* structure to get all Pnmi-Data */ - int RlmtMode; /* link check mode to set */ - int RlmtNets; /* Number of nets */ - - SK_IOC IoBase; /* register set of adapter */ - int BoardLevel; /* level of active hw init (0-2) */ - - SK_U32 AllocFlag; /* flag allocation of resources */ - struct pci_dev *PciDev; /* for access to pci config space */ - struct SK_NET_DEVICE *dev[2]; /* pointer to device struct */ - - int RxBufSize; /* length of receive buffers */ - struct net_device_stats stats; /* linux 'netstat -i' statistics */ - int Index; /* internal board index number */ - - /* adapter RAM sizes for queues of active port */ - int RxQueueSize; /* memory used for receive queue */ - int TxSQueueSize; /* memory used for sync. tx queue */ - int TxAQueueSize; /* memory used for async. tx queue */ - - int PromiscCount; /* promiscuous mode counter */ - int AllMultiCount; /* allmulticast mode counter */ - int MulticCount; /* number of different MC */ - /* addresses for this board */ - /* (may be more than HW can)*/ - - int HWRevision; /* Hardware revision */ - int ActivePort; /* the active XMAC port */ - int MaxPorts; /* number of activated ports */ - int TxDescrPerRing; /* # of descriptors per tx ring */ - int RxDescrPerRing; /* # of descriptors per rx ring */ - - caddr_t pDescrMem; /* Pointer to the descriptor area */ - dma_addr_t pDescrMemDMA; /* PCI DMA address of area */ - - /* the port structures with descriptor rings */ - TX_PORT TxPort[SK_MAX_MACS][2]; - RX_PORT RxPort[SK_MAX_MACS]; - - SK_BOOL CheckQueue; /* check event queue soon */ - SK_TIMER DrvCleanupTimer;/* to check for pending descriptors */ - DIM_INFO DynIrqModInfo; /* all data related to DIM */ - - /* Only for tests */ - int PortDown; - int ChipsetType; /* Chipset family type - * 0 == Genesis family support - * 1 == Yukon family support - */ -#ifdef SK_DIAG_SUPPORT - SK_U32 DiagModeActive; /* is diag active? */ - SK_BOOL DiagFlowCtrl; /* for control purposes */ - SK_PNMI_STRUCT_DATA PnmiBackup; /* backup structure for all Pnmi-Data */ - SK_BOOL WasIfUp[SK_MAX_MACS]; /* for OpenClose while - * DIAG is busy with NIC - */ -#endif - -}; - - -#endif /* __INC_SKDRV2ND_H */ - diff --git a/drivers/net/sk98lin/h/skerror.h b/drivers/net/sk98lin/h/skerror.h deleted file mode 100644 index da062f766238..000000000000 --- a/drivers/net/sk98lin/h/skerror.h +++ /dev/null @@ -1,55 +0,0 @@ -/****************************************************************************** - * - * Name: skerror.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.7 $ - * Date: $Date: 2003/05/13 17:25:13 $ - * Purpose: SK specific Error log support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef _INC_SKERROR_H_ -#define _INC_SKERROR_H_ - -/* - * Define Error Classes - */ -#define SK_ERRCL_OTHER (0) /* Other error */ -#define SK_ERRCL_CONFIG (1L<<0) /* Configuration error */ -#define SK_ERRCL_INIT (1L<<1) /* Initialization error */ -#define SK_ERRCL_NORES (1L<<2) /* Out of Resources error */ -#define SK_ERRCL_SW (1L<<3) /* Internal Software error */ -#define SK_ERRCL_HW (1L<<4) /* Hardware Failure */ -#define SK_ERRCL_COMM (1L<<5) /* Communication error */ - - -/* - * Define Error Code Bases - */ -#define SK_ERRBASE_RLMT 100 /* Base Error number for RLMT */ -#define SK_ERRBASE_HWINIT 200 /* Base Error number for HWInit */ -#define SK_ERRBASE_VPD 300 /* Base Error number for VPD */ -#define SK_ERRBASE_PNMI 400 /* Base Error number for PNMI */ -#define SK_ERRBASE_CSUM 500 /* Base Error number for Checksum */ -#define SK_ERRBASE_SIRQ 600 /* Base Error number for Special IRQ */ -#define SK_ERRBASE_I2C 700 /* Base Error number for I2C module */ -#define SK_ERRBASE_QUEUE 800 /* Base Error number for Scheduler */ -#define SK_ERRBASE_ADDR 900 /* Base Error number for Address module */ -#define SK_ERRBASE_PECP 1000 /* Base Error number for PECP */ -#define SK_ERRBASE_DRV 1100 /* Base Error number for Driver */ - -#endif /* _INC_SKERROR_H_ */ diff --git a/drivers/net/sk98lin/h/skgedrv.h b/drivers/net/sk98lin/h/skgedrv.h deleted file mode 100644 index 44fd4c3de818..000000000000 --- a/drivers/net/sk98lin/h/skgedrv.h +++ /dev/null @@ -1,51 +0,0 @@ -/****************************************************************************** - * - * Name: skgedrv.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.10 $ - * Date: $Date: 2003/07/04 12:25:01 $ - * Purpose: Interface with the driver - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_SKGEDRV_H_ -#define __INC_SKGEDRV_H_ - -/* defines ********************************************************************/ - -/* - * Define the driver events. - * Usually the events are defined by the destination module. - * In case of the driver we put the definition of the events here. - */ -#define SK_DRV_PORT_RESET 1 /* The port needs to be reset */ -#define SK_DRV_NET_UP 2 /* The net is operational */ -#define SK_DRV_NET_DOWN 3 /* The net is down */ -#define SK_DRV_SWITCH_SOFT 4 /* Ports switch with both links connected */ -#define SK_DRV_SWITCH_HARD 5 /* Port switch due to link failure */ -#define SK_DRV_RLMT_SEND 6 /* Send a RLMT packet */ -#define SK_DRV_ADAP_FAIL 7 /* The whole adapter fails */ -#define SK_DRV_PORT_FAIL 8 /* One port fails */ -#define SK_DRV_SWITCH_INTERN 9 /* Port switch by the driver itself */ -#define SK_DRV_POWER_DOWN 10 /* Power down mode */ -#define SK_DRV_TIMER 11 /* Timer for free use */ -#ifdef SK_NO_RLMT -#define SK_DRV_LINK_UP 12 /* Link Up event for driver */ -#define SK_DRV_LINK_DOWN 13 /* Link Down event for driver */ -#endif -#define SK_DRV_DOWNSHIFT_DET 14 /* Downshift 4-Pair / 2-Pair (YUKON only) */ -#endif /* __INC_SKGEDRV_H_ */ diff --git a/drivers/net/sk98lin/h/skgehw.h b/drivers/net/sk98lin/h/skgehw.h deleted file mode 100644 index f6282b7956db..000000000000 --- a/drivers/net/sk98lin/h/skgehw.h +++ /dev/null @@ -1,2126 +0,0 @@ -/****************************************************************************** - * - * Name: skgehw.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.56 $ - * Date: $Date: 2003/09/23 09:01:00 $ - * Purpose: Defines and Macros for the Gigabit Ethernet Adapter Product Family - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_SKGEHW_H -#define __INC_SKGEHW_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -#define BIT_31 (1UL << 31) -#define BIT_30 (1L << 30) -#define BIT_29 (1L << 29) -#define BIT_28 (1L << 28) -#define BIT_27 (1L << 27) -#define BIT_26 (1L << 26) -#define BIT_25 (1L << 25) -#define BIT_24 (1L << 24) -#define BIT_23 (1L << 23) -#define BIT_22 (1L << 22) -#define BIT_21 (1L << 21) -#define BIT_20 (1L << 20) -#define BIT_19 (1L << 19) -#define BIT_18 (1L << 18) -#define BIT_17 (1L << 17) -#define BIT_16 (1L << 16) -#define BIT_15 (1L << 15) -#define BIT_14 (1L << 14) -#define BIT_13 (1L << 13) -#define BIT_12 (1L << 12) -#define BIT_11 (1L << 11) -#define BIT_10 (1L << 10) -#define BIT_9 (1L << 9) -#define BIT_8 (1L << 8) -#define BIT_7 (1L << 7) -#define BIT_6 (1L << 6) -#define BIT_5 (1L << 5) -#define BIT_4 (1L << 4) -#define BIT_3 (1L << 3) -#define BIT_2 (1L << 2) -#define BIT_1 (1L << 1) -#define BIT_0 1L - -#define BIT_15S (1U << 15) -#define BIT_14S (1 << 14) -#define BIT_13S (1 << 13) -#define BIT_12S (1 << 12) -#define BIT_11S (1 << 11) -#define BIT_10S (1 << 10) -#define BIT_9S (1 << 9) -#define BIT_8S (1 << 8) -#define BIT_7S (1 << 7) -#define BIT_6S (1 << 6) -#define BIT_5S (1 << 5) -#define BIT_4S (1 << 4) -#define BIT_3S (1 << 3) -#define BIT_2S (1 << 2) -#define BIT_1S (1 << 1) -#define BIT_0S 1 - -#define SHIFT31(x) ((x) << 31) -#define SHIFT30(x) ((x) << 30) -#define SHIFT29(x) ((x) << 29) -#define SHIFT28(x) ((x) << 28) -#define SHIFT27(x) ((x) << 27) -#define SHIFT26(x) ((x) << 26) -#define SHIFT25(x) ((x) << 25) -#define SHIFT24(x) ((x) << 24) -#define SHIFT23(x) ((x) << 23) -#define SHIFT22(x) ((x) << 22) -#define SHIFT21(x) ((x) << 21) -#define SHIFT20(x) ((x) << 20) -#define SHIFT19(x) ((x) << 19) -#define SHIFT18(x) ((x) << 18) -#define SHIFT17(x) ((x) << 17) -#define SHIFT16(x) ((x) << 16) -#define SHIFT15(x) ((x) << 15) -#define SHIFT14(x) ((x) << 14) -#define SHIFT13(x) ((x) << 13) -#define SHIFT12(x) ((x) << 12) -#define SHIFT11(x) ((x) << 11) -#define SHIFT10(x) ((x) << 10) -#define SHIFT9(x) ((x) << 9) -#define SHIFT8(x) ((x) << 8) -#define SHIFT7(x) ((x) << 7) -#define SHIFT6(x) ((x) << 6) -#define SHIFT5(x) ((x) << 5) -#define SHIFT4(x) ((x) << 4) -#define SHIFT3(x) ((x) << 3) -#define SHIFT2(x) ((x) << 2) -#define SHIFT1(x) ((x) << 1) -#define SHIFT0(x) ((x) << 0) - -/* - * Configuration Space header - * Since this module is used for different OS', those may be - * duplicate on some of them (e.g. Linux). But to keep the - * common source, we have to live with this... - */ -#define PCI_VENDOR_ID 0x00 /* 16 bit Vendor ID */ -#define PCI_DEVICE_ID 0x02 /* 16 bit Device ID */ -#define PCI_COMMAND 0x04 /* 16 bit Command */ -#define PCI_STATUS 0x06 /* 16 bit Status */ -#define PCI_REV_ID 0x08 /* 8 bit Revision ID */ -#define PCI_CLASS_CODE 0x09 /* 24 bit Class Code */ -#define PCI_CACHE_LSZ 0x0c /* 8 bit Cache Line Size */ -#define PCI_LAT_TIM 0x0d /* 8 bit Latency Timer */ -#define PCI_HEADER_T 0x0e /* 8 bit Header Type */ -#define PCI_BIST 0x0f /* 8 bit Built-in selftest */ -#define PCI_BASE_1ST 0x10 /* 32 bit 1st Base address */ -#define PCI_BASE_2ND 0x14 /* 32 bit 2nd Base address */ - /* Byte 0x18..0x2b: reserved */ -#define PCI_SUB_VID 0x2c /* 16 bit Subsystem Vendor ID */ -#define PCI_SUB_ID 0x2e /* 16 bit Subsystem ID */ -#define PCI_BASE_ROM 0x30 /* 32 bit Expansion ROM Base Address */ -#define PCI_CAP_PTR 0x34 /* 8 bit Capabilities Ptr */ - /* Byte 0x35..0x3b: reserved */ -#define PCI_IRQ_LINE 0x3c /* 8 bit Interrupt Line */ -#define PCI_IRQ_PIN 0x3d /* 8 bit Interrupt Pin */ -#define PCI_MIN_GNT 0x3e /* 8 bit Min_Gnt */ -#define PCI_MAX_LAT 0x3f /* 8 bit Max_Lat */ - /* Device Dependent Region */ -#define PCI_OUR_REG_1 0x40 /* 32 bit Our Register 1 */ -#define PCI_OUR_REG_2 0x44 /* 32 bit Our Register 2 */ - /* Power Management Region */ -#define PCI_PM_CAP_ID 0x48 /* 8 bit Power Management Cap. ID */ -#define PCI_PM_NITEM 0x49 /* 8 bit Next Item Ptr */ -#define PCI_PM_CAP_REG 0x4a /* 16 bit Power Management Capabilities */ -#define PCI_PM_CTL_STS 0x4c /* 16 bit Power Manag. Control/Status */ - /* Byte 0x4e: reserved */ -#define PCI_PM_DAT_REG 0x4f /* 8 bit Power Manag. Data Register */ - /* VPD Region */ -#define PCI_VPD_CAP_ID 0x50 /* 8 bit VPD Cap. ID */ -#define PCI_VPD_NITEM 0x51 /* 8 bit Next Item Ptr */ -#define PCI_VPD_ADR_REG 0x52 /* 16 bit VPD Address Register */ -#define PCI_VPD_DAT_REG 0x54 /* 32 bit VPD Data Register */ - /* Byte 0x58..0x59: reserved */ -#define PCI_SER_LD_CTRL 0x5a /* 16 bit SEEPROM Loader Ctrl (YUKON only) */ - /* Byte 0x5c..0xff: reserved */ - -/* - * I2C Address (PCI Config) - * - * Note: The temperature and voltage sensors are relocated on a different - * I2C bus. - */ -#define I2C_ADDR_VPD 0xa0 /* I2C address for the VPD EEPROM */ - -/* - * Define Bits and Values of the registers - */ -/* PCI_COMMAND 16 bit Command */ - /* Bit 15..11: reserved */ -#define PCI_INT_DIS BIT_10S /* Interrupt INTx# disable (PCI 2.3) */ -#define PCI_FBTEN BIT_9S /* Fast Back-To-Back enable */ -#define PCI_SERREN BIT_8S /* SERR enable */ -#define PCI_ADSTEP BIT_7S /* Address Stepping */ -#define PCI_PERREN BIT_6S /* Parity Report Response enable */ -#define PCI_VGA_SNOOP BIT_5S /* VGA palette snoop */ -#define PCI_MWIEN BIT_4S /* Memory write an inv cycl ena */ -#define PCI_SCYCEN BIT_3S /* Special Cycle enable */ -#define PCI_BMEN BIT_2S /* Bus Master enable */ -#define PCI_MEMEN BIT_1S /* Memory Space Access enable */ -#define PCI_IOEN BIT_0S /* I/O Space Access enable */ - -#define PCI_COMMAND_VAL (PCI_FBTEN | PCI_SERREN | PCI_PERREN | PCI_MWIEN |\ - PCI_BMEN | PCI_MEMEN | PCI_IOEN) - -/* PCI_STATUS 16 bit Status */ -#define PCI_PERR BIT_15S /* Parity Error */ -#define PCI_SERR BIT_14S /* Signaled SERR */ -#define PCI_RMABORT BIT_13S /* Received Master Abort */ -#define PCI_RTABORT BIT_12S /* Received Target Abort */ - /* Bit 11: reserved */ -#define PCI_DEVSEL (3<<9) /* Bit 10.. 9: DEVSEL Timing */ -#define PCI_DEV_FAST (0<<9) /* fast */ -#define PCI_DEV_MEDIUM (1<<9) /* medium */ -#define PCI_DEV_SLOW (2<<9) /* slow */ -#define PCI_DATAPERR BIT_8S /* DATA Parity error detected */ -#define PCI_FB2BCAP BIT_7S /* Fast Back-to-Back Capability */ -#define PCI_UDF BIT_6S /* User Defined Features */ -#define PCI_66MHZCAP BIT_5S /* 66 MHz PCI bus clock capable */ -#define PCI_NEWCAP BIT_4S /* New cap. list implemented */ -#define PCI_INT_STAT BIT_3S /* Interrupt INTx# Status (PCI 2.3) */ - /* Bit 2.. 0: reserved */ - -#define PCI_ERRBITS (PCI_PERR | PCI_SERR | PCI_RMABORT | PCI_RTABORT |\ - PCI_DATAPERR) - -/* PCI_CLASS_CODE 24 bit Class Code */ -/* Byte 2: Base Class (02) */ -/* Byte 1: SubClass (00) */ -/* Byte 0: Programming Interface (00) */ - -/* PCI_CACHE_LSZ 8 bit Cache Line Size */ -/* Possible values: 0,2,4,8,16,32,64,128 */ - -/* PCI_HEADER_T 8 bit Header Type */ -#define PCI_HD_MF_DEV BIT_7S /* 0= single, 1= multi-func dev */ -#define PCI_HD_TYPE 0x7f /* Bit 6..0: Header Layout 0= normal */ - -/* PCI_BIST 8 bit Built-in selftest */ -/* Built-in Self test not supported (optional) */ - -/* PCI_BASE_1ST 32 bit 1st Base address */ -#define PCI_MEMSIZE 0x4000L /* use 16 kB Memory Base */ -#define PCI_MEMBASE_MSK 0xffffc000L /* Bit 31..14: Memory Base Address */ -#define PCI_MEMSIZE_MSK 0x00003ff0L /* Bit 13.. 4: Memory Size Req. */ -#define PCI_PREFEN BIT_3 /* Prefetchable */ -#define PCI_MEM_TYP (3L<<2) /* Bit 2.. 1: Memory Type */ -#define PCI_MEM32BIT (0L<<1) /* Base addr anywhere in 32 Bit range */ -#define PCI_MEM1M (1L<<1) /* Base addr below 1 MegaByte */ -#define PCI_MEM64BIT (2L<<1) /* Base addr anywhere in 64 Bit range */ -#define PCI_MEMSPACE BIT_0 /* Memory Space Indicator */ - -/* PCI_BASE_2ND 32 bit 2nd Base address */ -#define PCI_IOBASE 0xffffff00L /* Bit 31.. 8: I/O Base address */ -#define PCI_IOSIZE 0x000000fcL /* Bit 7.. 2: I/O Size Requirements */ - /* Bit 1: reserved */ -#define PCI_IOSPACE BIT_0 /* I/O Space Indicator */ - -/* PCI_BASE_ROM 32 bit Expansion ROM Base Address */ -#define PCI_ROMBASE_MSK 0xfffe0000L /* Bit 31..17: ROM Base address */ -#define PCI_ROMBASE_SIZ (0x1cL<<14) /* Bit 16..14: Treat as Base or Size */ -#define PCI_ROMSIZE (0x38L<<11) /* Bit 13..11: ROM Size Requirements */ - /* Bit 10.. 1: reserved */ -#define PCI_ROMEN BIT_0 /* Address Decode enable */ - -/* Device Dependent Region */ -/* PCI_OUR_REG_1 32 bit Our Register 1 */ - /* Bit 31..29: reserved */ -#define PCI_PHY_COMA BIT_28 /* Set PHY to Coma Mode (YUKON only) */ -#define PCI_TEST_CAL BIT_27 /* Test PCI buffer calib. (YUKON only) */ -#define PCI_EN_CAL BIT_26 /* Enable PCI buffer calib. (YUKON only) */ -#define PCI_VIO BIT_25 /* PCI I/O Voltage, 0 = 3.3V, 1 = 5V */ -#define PCI_DIS_BOOT BIT_24 /* Disable BOOT via ROM */ -#define PCI_EN_IO BIT_23 /* Mapping to I/O space */ -#define PCI_EN_FPROM BIT_22 /* Enable FLASH mapping to memory */ - /* 1 = Map Flash to memory */ - /* 0 = Disable addr. dec */ -#define PCI_PAGESIZE (3L<<20) /* Bit 21..20: FLASH Page Size */ -#define PCI_PAGE_16 (0L<<20) /* 16 k pages */ -#define PCI_PAGE_32K (1L<<20) /* 32 k pages */ -#define PCI_PAGE_64K (2L<<20) /* 64 k pages */ -#define PCI_PAGE_128K (3L<<20) /* 128 k pages */ - /* Bit 19: reserved */ -#define PCI_PAGEREG (7L<<16) /* Bit 18..16: Page Register */ -#define PCI_NOTAR BIT_15 /* No turnaround cycle */ -#define PCI_FORCE_BE BIT_14 /* Assert all BEs on MR */ -#define PCI_DIS_MRL BIT_13 /* Disable Mem Read Line */ -#define PCI_DIS_MRM BIT_12 /* Disable Mem Read Multiple */ -#define PCI_DIS_MWI BIT_11 /* Disable Mem Write & Invalidate */ -#define PCI_DISC_CLS BIT_10 /* Disc: cacheLsz bound */ -#define PCI_BURST_DIS BIT_9 /* Burst Disable */ -#define PCI_DIS_PCI_CLK BIT_8 /* Disable PCI clock driving */ -#define PCI_SKEW_DAS (0xfL<<4) /* Bit 7.. 4: Skew Ctrl, DAS Ext */ -#define PCI_SKEW_BASE 0xfL /* Bit 3.. 0: Skew Ctrl, Base */ - - -/* PCI_OUR_REG_2 32 bit Our Register 2 */ -#define PCI_VPD_WR_THR (0xffL<<24) /* Bit 31..24: VPD Write Threshold */ -#define PCI_DEV_SEL (0x7fL<<17) /* Bit 23..17: EEPROM Device Select */ -#define PCI_VPD_ROM_SZ (7L<<14) /* Bit 16..14: VPD ROM Size */ - /* Bit 13..12: reserved */ -#define PCI_PATCH_DIR (0xfL<<8) /* Bit 11.. 8: Ext Patches dir 3..0 */ -#define PCI_PATCH_DIR_3 BIT_11 -#define PCI_PATCH_DIR_2 BIT_10 -#define PCI_PATCH_DIR_1 BIT_9 -#define PCI_PATCH_DIR_0 BIT_8 -#define PCI_EXT_PATCHS (0xfL<<4) /* Bit 7.. 4: Extended Patches 3..0 */ -#define PCI_EXT_PATCH_3 BIT_7 -#define PCI_EXT_PATCH_2 BIT_6 -#define PCI_EXT_PATCH_1 BIT_5 -#define PCI_EXT_PATCH_0 BIT_4 -#define PCI_EN_DUMMY_RD BIT_3 /* Enable Dummy Read */ -#define PCI_REV_DESC BIT_2 /* Reverse Desc. Bytes */ - /* Bit 1: reserved */ -#define PCI_USEDATA64 BIT_0 /* Use 64Bit Data bus ext */ - - -/* Power Management Region */ -/* PCI_PM_CAP_REG 16 bit Power Management Capabilities */ -#define PCI_PME_SUP_MSK (0x1f<<11) /* Bit 15..11: PM Event Support Mask */ -#define PCI_PME_D3C_SUP BIT_15S /* PME from D3cold Support (if Vaux) */ -#define PCI_PME_D3H_SUP BIT_14S /* PME from D3hot Support */ -#define PCI_PME_D2_SUP BIT_13S /* PME from D2 Support */ -#define PCI_PME_D1_SUP BIT_12S /* PME from D1 Support */ -#define PCI_PME_D0_SUP BIT_11S /* PME from D0 Support */ -#define PCI_PM_D2_SUP BIT_10S /* D2 Support in 33 MHz mode */ -#define PCI_PM_D1_SUP BIT_9S /* D1 Support */ - /* Bit 8.. 6: reserved */ -#define PCI_PM_DSI BIT_5S /* Device Specific Initialization */ -#define PCI_PM_APS BIT_4S /* Auxialiary Power Source */ -#define PCI_PME_CLOCK BIT_3S /* PM Event Clock */ -#define PCI_PM_VER_MSK 7 /* Bit 2.. 0: PM PCI Spec. version */ - -/* PCI_PM_CTL_STS 16 bit Power Management Control/Status */ -#define PCI_PME_STATUS BIT_15S /* PME Status (YUKON only) */ -#define PCI_PM_DAT_SCL (3<<13) /* Bit 14..13: Data Reg. scaling factor */ -#define PCI_PM_DAT_SEL (0xf<<9) /* Bit 12.. 9: PM data selector field */ -#define PCI_PME_EN BIT_8S /* Enable PME# generation (YUKON only) */ - /* Bit 7.. 2: reserved */ -#define PCI_PM_STATE_MSK 3 /* Bit 1.. 0: Power Management State */ - -#define PCI_PM_STATE_D0 0 /* D0: Operational (default) */ -#define PCI_PM_STATE_D1 1 /* D1: (YUKON only) */ -#define PCI_PM_STATE_D2 2 /* D2: (YUKON only) */ -#define PCI_PM_STATE_D3 3 /* D3: HOT, Power Down and Reset */ - -/* VPD Region */ -/* PCI_VPD_ADR_REG 16 bit VPD Address Register */ -#define PCI_VPD_FLAG BIT_15S /* starts VPD rd/wr cycle */ -#define PCI_VPD_ADR_MSK 0x7fffL /* Bit 14.. 0: VPD address mask */ - -/* Control Register File (Address Map) */ - -/* - * Bank 0 - */ -#define B0_RAP 0x0000 /* 8 bit Register Address Port */ - /* 0x0001 - 0x0003: reserved */ -#define B0_CTST 0x0004 /* 16 bit Control/Status register */ -#define B0_LED 0x0006 /* 8 Bit LED register */ -#define B0_POWER_CTRL 0x0007 /* 8 Bit Power Control reg (YUKON only) */ -#define B0_ISRC 0x0008 /* 32 bit Interrupt Source Register */ -#define B0_IMSK 0x000c /* 32 bit Interrupt Mask Register */ -#define B0_HWE_ISRC 0x0010 /* 32 bit HW Error Interrupt Src Reg */ -#define B0_HWE_IMSK 0x0014 /* 32 bit HW Error Interrupt Mask Reg */ -#define B0_SP_ISRC 0x0018 /* 32 bit Special Interrupt Source Reg */ - /* 0x001c: reserved */ - -/* B0 XMAC 1 registers (GENESIS only) */ -#define B0_XM1_IMSK 0x0020 /* 16 bit r/w XMAC 1 Interrupt Mask Register*/ - /* 0x0022 - 0x0027: reserved */ -#define B0_XM1_ISRC 0x0028 /* 16 bit ro XMAC 1 Interrupt Status Reg */ - /* 0x002a - 0x002f: reserved */ -#define B0_XM1_PHY_ADDR 0x0030 /* 16 bit r/w XMAC 1 PHY Address Register */ - /* 0x0032 - 0x0033: reserved */ -#define B0_XM1_PHY_DATA 0x0034 /* 16 bit r/w XMAC 1 PHY Data Register */ - /* 0x0036 - 0x003f: reserved */ - -/* B0 XMAC 2 registers (GENESIS only) */ -#define B0_XM2_IMSK 0x0040 /* 16 bit r/w XMAC 2 Interrupt Mask Register*/ - /* 0x0042 - 0x0047: reserved */ -#define B0_XM2_ISRC 0x0048 /* 16 bit ro XMAC 2 Interrupt Status Reg */ - /* 0x004a - 0x004f: reserved */ -#define B0_XM2_PHY_ADDR 0x0050 /* 16 bit r/w XMAC 2 PHY Address Register */ - /* 0x0052 - 0x0053: reserved */ -#define B0_XM2_PHY_DATA 0x0054 /* 16 bit r/w XMAC 2 PHY Data Register */ - /* 0x0056 - 0x005f: reserved */ - -/* BMU Control Status Registers */ -#define B0_R1_CSR 0x0060 /* 32 bit BMU Ctrl/Stat Rx Queue 1 */ -#define B0_R2_CSR 0x0064 /* 32 bit BMU Ctrl/Stat Rx Queue 2 */ -#define B0_XS1_CSR 0x0068 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -#define B0_XA1_CSR 0x006c /* 32 bit BMU Ctrl/Stat Async Tx Queue 1*/ -#define B0_XS2_CSR 0x0070 /* 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -#define B0_XA2_CSR 0x0074 /* 32 bit BMU Ctrl/Stat Async Tx Queue 2*/ - /* 0x0078 - 0x007f: reserved */ - -/* - * Bank 1 - * - completely empty (this is the RAP Block window) - * Note: if RAP = 1 this page is reserved - */ - -/* - * Bank 2 - */ -/* NA reg = 48 bit Network Address Register, 3x16 or 8x8 bit readable */ -#define B2_MAC_1 0x0100 /* NA reg MAC Address 1 */ - /* 0x0106 - 0x0107: reserved */ -#define B2_MAC_2 0x0108 /* NA reg MAC Address 2 */ - /* 0x010e - 0x010f: reserved */ -#define B2_MAC_3 0x0110 /* NA reg MAC Address 3 */ - /* 0x0116 - 0x0117: reserved */ -#define B2_CONN_TYP 0x0118 /* 8 bit Connector type */ -#define B2_PMD_TYP 0x0119 /* 8 bit PMD type */ -#define B2_MAC_CFG 0x011a /* 8 bit MAC Configuration / Chip Revision */ -#define B2_CHIP_ID 0x011b /* 8 bit Chip Identification Number */ - /* Eprom registers are currently of no use */ -#define B2_E_0 0x011c /* 8 bit EPROM Byte 0 (ext. SRAM size */ -#define B2_E_1 0x011d /* 8 bit EPROM Byte 1 (PHY type) */ -#define B2_E_2 0x011e /* 8 bit EPROM Byte 2 */ -#define B2_E_3 0x011f /* 8 bit EPROM Byte 3 */ -#define B2_FAR 0x0120 /* 32 bit Flash-Prom Addr Reg/Cnt */ -#define B2_FDP 0x0124 /* 8 bit Flash-Prom Data Port */ - /* 0x0125 - 0x0127: reserved */ -#define B2_LD_CTRL 0x0128 /* 8 bit EPROM loader control register */ -#define B2_LD_TEST 0x0129 /* 8 bit EPROM loader test register */ - /* 0x012a - 0x012f: reserved */ -#define B2_TI_INI 0x0130 /* 32 bit Timer Init Value */ -#define B2_TI_VAL 0x0134 /* 32 bit Timer Value */ -#define B2_TI_CTRL 0x0138 /* 8 bit Timer Control */ -#define B2_TI_TEST 0x0139 /* 8 Bit Timer Test */ - /* 0x013a - 0x013f: reserved */ -#define B2_IRQM_INI 0x0140 /* 32 bit IRQ Moderation Timer Init Reg.*/ -#define B2_IRQM_VAL 0x0144 /* 32 bit IRQ Moderation Timer Value */ -#define B2_IRQM_CTRL 0x0148 /* 8 bit IRQ Moderation Timer Control */ -#define B2_IRQM_TEST 0x0149 /* 8 bit IRQ Moderation Timer Test */ -#define B2_IRQM_MSK 0x014c /* 32 bit IRQ Moderation Mask */ -#define B2_IRQM_HWE_MSK 0x0150 /* 32 bit IRQ Moderation HW Error Mask */ - /* 0x0154 - 0x0157: reserved */ -#define B2_TST_CTRL1 0x0158 /* 8 bit Test Control Register 1 */ -#define B2_TST_CTRL2 0x0159 /* 8 bit Test Control Register 2 */ - /* 0x015a - 0x015b: reserved */ -#define B2_GP_IO 0x015c /* 32 bit General Purpose I/O Register */ -#define B2_I2C_CTRL 0x0160 /* 32 bit I2C HW Control Register */ -#define B2_I2C_DATA 0x0164 /* 32 bit I2C HW Data Register */ -#define B2_I2C_IRQ 0x0168 /* 32 bit I2C HW IRQ Register */ -#define B2_I2C_SW 0x016c /* 32 bit I2C SW Port Register */ - -/* Blink Source Counter (GENESIS only) */ -#define B2_BSC_INI 0x0170 /* 32 bit Blink Source Counter Init Val */ -#define B2_BSC_VAL 0x0174 /* 32 bit Blink Source Counter Value */ -#define B2_BSC_CTRL 0x0178 /* 8 bit Blink Source Counter Control */ -#define B2_BSC_STAT 0x0179 /* 8 bit Blink Source Counter Status */ -#define B2_BSC_TST 0x017a /* 16 bit Blink Source Counter Test Reg */ - /* 0x017c - 0x017f: reserved */ - -/* - * Bank 3 - */ -/* RAM Random Registers */ -#define B3_RAM_ADDR 0x0180 /* 32 bit RAM Address, to read or write */ -#define B3_RAM_DATA_LO 0x0184 /* 32 bit RAM Data Word (low dWord) */ -#define B3_RAM_DATA_HI 0x0188 /* 32 bit RAM Data Word (high dWord) */ - /* 0x018c - 0x018f: reserved */ - -/* RAM Interface Registers */ -/* - * The HW-Spec. calls this registers Timeout Value 0..11. But this names are - * not usable in SW. Please notice these are NOT real timeouts, these are - * the number of qWords transferred continuously. - */ -#define B3_RI_WTO_R1 0x0190 /* 8 bit WR Timeout Queue R1 (TO0) */ -#define B3_RI_WTO_XA1 0x0191 /* 8 bit WR Timeout Queue XA1 (TO1) */ -#define B3_RI_WTO_XS1 0x0192 /* 8 bit WR Timeout Queue XS1 (TO2) */ -#define B3_RI_RTO_R1 0x0193 /* 8 bit RD Timeout Queue R1 (TO3) */ -#define B3_RI_RTO_XA1 0x0194 /* 8 bit RD Timeout Queue XA1 (TO4) */ -#define B3_RI_RTO_XS1 0x0195 /* 8 bit RD Timeout Queue XS1 (TO5) */ -#define B3_RI_WTO_R2 0x0196 /* 8 bit WR Timeout Queue R2 (TO6) */ -#define B3_RI_WTO_XA2 0x0197 /* 8 bit WR Timeout Queue XA2 (TO7) */ -#define B3_RI_WTO_XS2 0x0198 /* 8 bit WR Timeout Queue XS2 (TO8) */ -#define B3_RI_RTO_R2 0x0199 /* 8 bit RD Timeout Queue R2 (TO9) */ -#define B3_RI_RTO_XA2 0x019a /* 8 bit RD Timeout Queue XA2 (TO10)*/ -#define B3_RI_RTO_XS2 0x019b /* 8 bit RD Timeout Queue XS2 (TO11)*/ -#define B3_RI_TO_VAL 0x019c /* 8 bit Current Timeout Count Val */ - /* 0x019d - 0x019f: reserved */ -#define B3_RI_CTRL 0x01a0 /* 16 bit RAM Interface Control Register */ -#define B3_RI_TEST 0x01a2 /* 8 bit RAM Interface Test Register */ - /* 0x01a3 - 0x01af: reserved */ - -/* MAC Arbiter Registers (GENESIS only) */ -/* these are the no. of qWord transferred continuously and NOT real timeouts */ -#define B3_MA_TOINI_RX1 0x01b0 /* 8 bit Timeout Init Val Rx Path MAC 1 */ -#define B3_MA_TOINI_RX2 0x01b1 /* 8 bit Timeout Init Val Rx Path MAC 2 */ -#define B3_MA_TOINI_TX1 0x01b2 /* 8 bit Timeout Init Val Tx Path MAC 1 */ -#define B3_MA_TOINI_TX2 0x01b3 /* 8 bit Timeout Init Val Tx Path MAC 2 */ -#define B3_MA_TOVAL_RX1 0x01b4 /* 8 bit Timeout Value Rx Path MAC 1 */ -#define B3_MA_TOVAL_RX2 0x01b5 /* 8 bit Timeout Value Rx Path MAC 1 */ -#define B3_MA_TOVAL_TX1 0x01b6 /* 8 bit Timeout Value Tx Path MAC 2 */ -#define B3_MA_TOVAL_TX2 0x01b7 /* 8 bit Timeout Value Tx Path MAC 2 */ -#define B3_MA_TO_CTRL 0x01b8 /* 16 bit MAC Arbiter Timeout Ctrl Reg */ -#define B3_MA_TO_TEST 0x01ba /* 16 bit MAC Arbiter Timeout Test Reg */ - /* 0x01bc - 0x01bf: reserved */ -#define B3_MA_RCINI_RX1 0x01c0 /* 8 bit Recovery Init Val Rx Path MAC 1 */ -#define B3_MA_RCINI_RX2 0x01c1 /* 8 bit Recovery Init Val Rx Path MAC 2 */ -#define B3_MA_RCINI_TX1 0x01c2 /* 8 bit Recovery Init Val Tx Path MAC 1 */ -#define B3_MA_RCINI_TX2 0x01c3 /* 8 bit Recovery Init Val Tx Path MAC 2 */ -#define B3_MA_RCVAL_RX1 0x01c4 /* 8 bit Recovery Value Rx Path MAC 1 */ -#define B3_MA_RCVAL_RX2 0x01c5 /* 8 bit Recovery Value Rx Path MAC 1 */ -#define B3_MA_RCVAL_TX1 0x01c6 /* 8 bit Recovery Value Tx Path MAC 2 */ -#define B3_MA_RCVAL_TX2 0x01c7 /* 8 bit Recovery Value Tx Path MAC 2 */ -#define B3_MA_RC_CTRL 0x01c8 /* 16 bit MAC Arbiter Recovery Ctrl Reg */ -#define B3_MA_RC_TEST 0x01ca /* 16 bit MAC Arbiter Recovery Test Reg */ - /* 0x01cc - 0x01cf: reserved */ - -/* Packet Arbiter Registers (GENESIS only) */ -/* these are real timeouts */ -#define B3_PA_TOINI_RX1 0x01d0 /* 16 bit Timeout Init Val Rx Path MAC 1 */ - /* 0x01d2 - 0x01d3: reserved */ -#define B3_PA_TOINI_RX2 0x01d4 /* 16 bit Timeout Init Val Rx Path MAC 2 */ - /* 0x01d6 - 0x01d7: reserved */ -#define B3_PA_TOINI_TX1 0x01d8 /* 16 bit Timeout Init Val Tx Path MAC 1 */ - /* 0x01da - 0x01db: reserved */ -#define B3_PA_TOINI_TX2 0x01dc /* 16 bit Timeout Init Val Tx Path MAC 2 */ - /* 0x01de - 0x01df: reserved */ -#define B3_PA_TOVAL_RX1 0x01e0 /* 16 bit Timeout Val Rx Path MAC 1 */ - /* 0x01e2 - 0x01e3: reserved */ -#define B3_PA_TOVAL_RX2 0x01e4 /* 16 bit Timeout Val Rx Path MAC 2 */ - /* 0x01e6 - 0x01e7: reserved */ -#define B3_PA_TOVAL_TX1 0x01e8 /* 16 bit Timeout Val Tx Path MAC 1 */ - /* 0x01ea - 0x01eb: reserved */ -#define B3_PA_TOVAL_TX2 0x01ec /* 16 bit Timeout Val Tx Path MAC 2 */ - /* 0x01ee - 0x01ef: reserved */ -#define B3_PA_CTRL 0x01f0 /* 16 bit Packet Arbiter Ctrl Register */ -#define B3_PA_TEST 0x01f2 /* 16 bit Packet Arbiter Test Register */ - /* 0x01f4 - 0x01ff: reserved */ - -/* - * Bank 4 - 5 - */ -/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ -#define TXA_ITI_INI 0x0200 /* 32 bit Tx Arb Interval Timer Init Val*/ -#define TXA_ITI_VAL 0x0204 /* 32 bit Tx Arb Interval Timer Value */ -#define TXA_LIM_INI 0x0208 /* 32 bit Tx Arb Limit Counter Init Val */ -#define TXA_LIM_VAL 0x020c /* 32 bit Tx Arb Limit Counter Value */ -#define TXA_CTRL 0x0210 /* 8 bit Tx Arbiter Control Register */ -#define TXA_TEST 0x0211 /* 8 bit Tx Arbiter Test Register */ -#define TXA_STAT 0x0212 /* 8 bit Tx Arbiter Status Register */ - /* 0x0213 - 0x027f: reserved */ - /* 0x0280 - 0x0292: MAC 2 */ - /* 0x0213 - 0x027f: reserved */ - -/* - * Bank 6 - */ -/* External registers (GENESIS only) */ -#define B6_EXT_REG 0x0300 - -/* - * Bank 7 - */ -/* This is a copy of the Configuration register file (lower half) */ -#define B7_CFG_SPC 0x0380 - -/* - * Bank 8 - 15 - */ -/* Receive and Transmit Queue Registers, use Q_ADDR() to access */ -#define B8_Q_REGS 0x0400 - -/* Queue Register Offsets, use Q_ADDR() to access */ -#define Q_D 0x00 /* 8*32 bit Current Descriptor */ -#define Q_DA_L 0x20 /* 32 bit Current Descriptor Address Low dWord */ -#define Q_DA_H 0x24 /* 32 bit Current Descriptor Address High dWord */ -#define Q_AC_L 0x28 /* 32 bit Current Address Counter Low dWord */ -#define Q_AC_H 0x2c /* 32 bit Current Address Counter High dWord */ -#define Q_BC 0x30 /* 32 bit Current Byte Counter */ -#define Q_CSR 0x34 /* 32 bit BMU Control/Status Register */ -#define Q_F 0x38 /* 32 bit Flag Register */ -#define Q_T1 0x3c /* 32 bit Test Register 1 */ -#define Q_T1_TR 0x3c /* 8 bit Test Register 1 Transfer SM */ -#define Q_T1_WR 0x3d /* 8 bit Test Register 1 Write Descriptor SM */ -#define Q_T1_RD 0x3e /* 8 bit Test Register 1 Read Descriptor SM */ -#define Q_T1_SV 0x3f /* 8 bit Test Register 1 Supervisor SM */ -#define Q_T2 0x40 /* 32 bit Test Register 2 */ -#define Q_T3 0x44 /* 32 bit Test Register 3 */ - /* 0x48 - 0x7f: reserved */ - -/* - * Bank 16 - 23 - */ -/* RAM Buffer Registers */ -#define B16_RAM_REGS 0x0800 - -/* RAM Buffer Register Offsets, use RB_ADDR() to access */ -#define RB_START 0x00 /* 32 bit RAM Buffer Start Address */ -#define RB_END 0x04 /* 32 bit RAM Buffer End Address */ -#define RB_WP 0x08 /* 32 bit RAM Buffer Write Pointer */ -#define RB_RP 0x0c /* 32 bit RAM Buffer Read Pointer */ -#define RB_RX_UTPP 0x10 /* 32 bit Rx Upper Threshold, Pause Pack */ -#define RB_RX_LTPP 0x14 /* 32 bit Rx Lower Threshold, Pause Pack */ -#define RB_RX_UTHP 0x18 /* 32 bit Rx Upper Threshold, High Prio */ -#define RB_RX_LTHP 0x1c /* 32 bit Rx Lower Threshold, High Prio */ - /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ -#define RB_PC 0x20 /* 32 bit RAM Buffer Packet Counter */ -#define RB_LEV 0x24 /* 32 bit RAM Buffer Level Register */ -#define RB_CTRL 0x28 /* 8 bit RAM Buffer Control Register */ -#define RB_TST1 0x29 /* 8 bit RAM Buffer Test Register 1 */ -#define RB_TST2 0x2A /* 8 bit RAM Buffer Test Register 2 */ - /* 0x2c - 0x7f: reserved */ - -/* - * Bank 24 - */ -/* - * Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) - * use MR_ADDR() to access - */ -#define RX_MFF_EA 0x0c00 /* 32 bit Receive MAC FIFO End Address */ -#define RX_MFF_WP 0x0c04 /* 32 bit Receive MAC FIFO Write Pointer */ - /* 0x0c08 - 0x0c0b: reserved */ -#define RX_MFF_RP 0x0c0c /* 32 bit Receive MAC FIFO Read Pointer */ -#define RX_MFF_PC 0x0c10 /* 32 bit Receive MAC FIFO Packet Cnt */ -#define RX_MFF_LEV 0x0c14 /* 32 bit Receive MAC FIFO Level */ -#define RX_MFF_CTRL1 0x0c18 /* 16 bit Receive MAC FIFO Control Reg 1*/ -#define RX_MFF_STAT_TO 0x0c1a /* 8 bit Receive MAC Status Timeout */ -#define RX_MFF_TIST_TO 0x0c1b /* 8 bit Receive MAC Time Stamp Timeout */ -#define RX_MFF_CTRL2 0x0c1c /* 8 bit Receive MAC FIFO Control Reg 2*/ -#define RX_MFF_TST1 0x0c1d /* 8 bit Receive MAC FIFO Test Reg 1 */ -#define RX_MFF_TST2 0x0c1e /* 8 bit Receive MAC FIFO Test Reg 2 */ - /* 0x0c1f: reserved */ -#define RX_LED_INI 0x0c20 /* 32 bit Receive LED Cnt Init Value */ -#define RX_LED_VAL 0x0c24 /* 32 bit Receive LED Cnt Current Value */ -#define RX_LED_CTRL 0x0c28 /* 8 bit Receive LED Cnt Control Reg */ -#define RX_LED_TST 0x0c29 /* 8 bit Receive LED Cnt Test Register */ - /* 0x0c2a - 0x0c2f: reserved */ -#define LNK_SYNC_INI 0x0c30 /* 32 bit Link Sync Cnt Init Value */ -#define LNK_SYNC_VAL 0x0c34 /* 32 bit Link Sync Cnt Current Value */ -#define LNK_SYNC_CTRL 0x0c38 /* 8 bit Link Sync Cnt Control Register */ -#define LNK_SYNC_TST 0x0c39 /* 8 bit Link Sync Cnt Test Register */ - /* 0x0c3a - 0x0c3b: reserved */ -#define LNK_LED_REG 0x0c3c /* 8 bit Link LED Register */ - /* 0x0c3d - 0x0c3f: reserved */ - -/* Receive GMAC FIFO (YUKON only), use MR_ADDR() to access */ -#define RX_GMF_EA 0x0c40 /* 32 bit Rx GMAC FIFO End Address */ -#define RX_GMF_AF_THR 0x0c44 /* 32 bit Rx GMAC FIFO Almost Full Thresh. */ -#define RX_GMF_CTRL_T 0x0c48 /* 32 bit Rx GMAC FIFO Control/Test */ -#define RX_GMF_FL_MSK 0x0c4c /* 32 bit Rx GMAC FIFO Flush Mask */ -#define RX_GMF_FL_THR 0x0c50 /* 32 bit Rx GMAC FIFO Flush Threshold */ - /* 0x0c54 - 0x0c5f: reserved */ -#define RX_GMF_WP 0x0c60 /* 32 bit Rx GMAC FIFO Write Pointer */ - /* 0x0c64 - 0x0c67: reserved */ -#define RX_GMF_WLEV 0x0c68 /* 32 bit Rx GMAC FIFO Write Level */ - /* 0x0c6c - 0x0c6f: reserved */ -#define RX_GMF_RP 0x0c70 /* 32 bit Rx GMAC FIFO Read Pointer */ - /* 0x0c74 - 0x0c77: reserved */ -#define RX_GMF_RLEV 0x0c78 /* 32 bit Rx GMAC FIFO Read Level */ - /* 0x0c7c - 0x0c7f: reserved */ - -/* - * Bank 25 - */ - /* 0x0c80 - 0x0cbf: MAC 2 */ - /* 0x0cc0 - 0x0cff: reserved */ - -/* - * Bank 26 - */ -/* - * Transmit MAC FIFO and Transmit LED Registers (GENESIS only), - * use MR_ADDR() to access - */ -#define TX_MFF_EA 0x0d00 /* 32 bit Transmit MAC FIFO End Address */ -#define TX_MFF_WP 0x0d04 /* 32 bit Transmit MAC FIFO WR Pointer */ -#define TX_MFF_WSP 0x0d08 /* 32 bit Transmit MAC FIFO WR Shadow Ptr */ -#define TX_MFF_RP 0x0d0c /* 32 bit Transmit MAC FIFO RD Pointer */ -#define TX_MFF_PC 0x0d10 /* 32 bit Transmit MAC FIFO Packet Cnt */ -#define TX_MFF_LEV 0x0d14 /* 32 bit Transmit MAC FIFO Level */ -#define TX_MFF_CTRL1 0x0d18 /* 16 bit Transmit MAC FIFO Ctrl Reg 1 */ -#define TX_MFF_WAF 0x0d1a /* 8 bit Transmit MAC Wait after flush */ - /* 0x0c1b: reserved */ -#define TX_MFF_CTRL2 0x0d1c /* 8 bit Transmit MAC FIFO Ctrl Reg 2 */ -#define TX_MFF_TST1 0x0d1d /* 8 bit Transmit MAC FIFO Test Reg 1 */ -#define TX_MFF_TST2 0x0d1e /* 8 bit Transmit MAC FIFO Test Reg 2 */ - /* 0x0d1f: reserved */ -#define TX_LED_INI 0x0d20 /* 32 bit Transmit LED Cnt Init Value */ -#define TX_LED_VAL 0x0d24 /* 32 bit Transmit LED Cnt Current Val */ -#define TX_LED_CTRL 0x0d28 /* 8 bit Transmit LED Cnt Control Reg */ -#define TX_LED_TST 0x0d29 /* 8 bit Transmit LED Cnt Test Reg */ - /* 0x0d2a - 0x0d3f: reserved */ - -/* Transmit GMAC FIFO (YUKON only), use MR_ADDR() to access */ -#define TX_GMF_EA 0x0d40 /* 32 bit Tx GMAC FIFO End Address */ -#define TX_GMF_AE_THR 0x0d44 /* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ -#define TX_GMF_CTRL_T 0x0d48 /* 32 bit Tx GMAC FIFO Control/Test */ - /* 0x0d4c - 0x0d5f: reserved */ -#define TX_GMF_WP 0x0d60 /* 32 bit Tx GMAC FIFO Write Pointer */ -#define TX_GMF_WSP 0x0d64 /* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ -#define TX_GMF_WLEV 0x0d68 /* 32 bit Tx GMAC FIFO Write Level */ - /* 0x0d6c - 0x0d6f: reserved */ -#define TX_GMF_RP 0x0d70 /* 32 bit Tx GMAC FIFO Read Pointer */ -#define TX_GMF_RSTP 0x0d74 /* 32 bit Tx GMAC FIFO Restart Pointer */ -#define TX_GMF_RLEV 0x0d78 /* 32 bit Tx GMAC FIFO Read Level */ - /* 0x0d7c - 0x0d7f: reserved */ - -/* - * Bank 27 - */ - /* 0x0d80 - 0x0dbf: MAC 2 */ - /* 0x0daa - 0x0dff: reserved */ - -/* - * Bank 28 - */ -/* Descriptor Poll Timer Registers */ -#define B28_DPT_INI 0x0e00 /* 24 bit Descriptor Poll Timer Init Val */ -#define B28_DPT_VAL 0x0e04 /* 24 bit Descriptor Poll Timer Curr Val */ -#define B28_DPT_CTRL 0x0e08 /* 8 bit Descriptor Poll Timer Ctrl Reg */ - /* 0x0e09: reserved */ -#define B28_DPT_TST 0x0e0a /* 8 bit Descriptor Poll Timer Test Reg */ - /* 0x0e0b: reserved */ - -/* Time Stamp Timer Registers (YUKON only) */ - /* 0x0e10: reserved */ -#define GMAC_TI_ST_VAL 0x0e14 /* 32 bit Time Stamp Timer Curr Val */ -#define GMAC_TI_ST_CTRL 0x0e18 /* 8 bit Time Stamp Timer Ctrl Reg */ - /* 0x0e19: reserved */ -#define GMAC_TI_ST_TST 0x0e1a /* 8 bit Time Stamp Timer Test Reg */ - /* 0x0e1b - 0x0e7f: reserved */ - -/* - * Bank 29 - */ - /* 0x0e80 - 0x0efc: reserved */ - -/* - * Bank 30 - */ -/* GMAC and GPHY Control Registers (YUKON only) */ -#define GMAC_CTRL 0x0f00 /* 32 bit GMAC Control Reg */ -#define GPHY_CTRL 0x0f04 /* 32 bit GPHY Control Reg */ -#define GMAC_IRQ_SRC 0x0f08 /* 8 bit GMAC Interrupt Source Reg */ - /* 0x0f09 - 0x0f0b: reserved */ -#define GMAC_IRQ_MSK 0x0f0c /* 8 bit GMAC Interrupt Mask Reg */ - /* 0x0f0d - 0x0f0f: reserved */ -#define GMAC_LINK_CTRL 0x0f10 /* 16 bit Link Control Reg */ - /* 0x0f14 - 0x0f1f: reserved */ - -/* Wake-up Frame Pattern Match Control Registers (YUKON only) */ - -#define WOL_REG_OFFS 0x20 /* HW-Bug: Address is + 0x20 against spec. */ - -#define WOL_CTRL_STAT 0x0f20 /* 16 bit WOL Control/Status Reg */ -#define WOL_MATCH_CTL 0x0f22 /* 8 bit WOL Match Control Reg */ -#define WOL_MATCH_RES 0x0f23 /* 8 bit WOL Match Result Reg */ -#define WOL_MAC_ADDR_LO 0x0f24 /* 32 bit WOL MAC Address Low */ -#define WOL_MAC_ADDR_HI 0x0f28 /* 16 bit WOL MAC Address High */ -#define WOL_PATT_RPTR 0x0f2c /* 8 bit WOL Pattern Read Ptr */ - -/* use this macro to access above registers */ -#define WOL_REG(Reg) ((Reg) + (pAC->GIni.GIWolOffs)) - - -/* WOL Pattern Length Registers (YUKON only) */ - -#define WOL_PATT_LEN_LO 0x0f30 /* 32 bit WOL Pattern Length 3..0 */ -#define WOL_PATT_LEN_HI 0x0f34 /* 24 bit WOL Pattern Length 6..4 */ - -/* WOL Pattern Counter Registers (YUKON only) */ - -#define WOL_PATT_CNT_0 0x0f38 /* 32 bit WOL Pattern Counter 3..0 */ -#define WOL_PATT_CNT_4 0x0f3c /* 24 bit WOL Pattern Counter 6..4 */ - /* 0x0f40 - 0x0f7f: reserved */ - -/* - * Bank 31 - */ -/* 0x0f80 - 0x0fff: reserved */ - -/* - * Bank 32 - 33 - */ -#define WOL_PATT_RAM_1 0x1000 /* WOL Pattern RAM Link 1 */ - -/* - * Bank 0x22 - 0x3f - */ -/* 0x1100 - 0x1fff: reserved */ - -/* - * Bank 0x40 - 0x4f - */ -#define BASE_XMAC_1 0x2000 /* XMAC 1 registers */ - -/* - * Bank 0x50 - 0x5f - */ - -#define BASE_GMAC_1 0x2800 /* GMAC 1 registers */ - -/* - * Bank 0x60 - 0x6f - */ -#define BASE_XMAC_2 0x3000 /* XMAC 2 registers */ - -/* - * Bank 0x70 - 0x7f - */ -#define BASE_GMAC_2 0x3800 /* GMAC 2 registers */ - -/* - * Control Register Bit Definitions: - */ -/* B0_RAP 8 bit Register Address Port */ - /* Bit 7: reserved */ -#define RAP_RAP 0x3f /* Bit 6..0: 0 = block 0,..,6f = block 6f */ - -/* B0_CTST 16 bit Control/Status register */ - /* Bit 15..14: reserved */ -#define CS_CLK_RUN_HOT BIT_13S /* CLK_RUN hot m. (YUKON-Lite only) */ -#define CS_CLK_RUN_RST BIT_12S /* CLK_RUN reset (YUKON-Lite only) */ -#define CS_CLK_RUN_ENA BIT_11S /* CLK_RUN enable (YUKON-Lite only) */ -#define CS_VAUX_AVAIL BIT_10S /* VAUX available (YUKON only) */ -#define CS_BUS_CLOCK BIT_9S /* Bus Clock 0/1 = 33/66 MHz */ -#define CS_BUS_SLOT_SZ BIT_8S /* Slot Size 0/1 = 32/64 bit slot */ -#define CS_ST_SW_IRQ BIT_7S /* Set IRQ SW Request */ -#define CS_CL_SW_IRQ BIT_6S /* Clear IRQ SW Request */ -#define CS_STOP_DONE BIT_5S /* Stop Master is finished */ -#define CS_STOP_MAST BIT_4S /* Command Bit to stop the master */ -#define CS_MRST_CLR BIT_3S /* Clear Master reset */ -#define CS_MRST_SET BIT_2S /* Set Master reset */ -#define CS_RST_CLR BIT_1S /* Clear Software reset */ -#define CS_RST_SET BIT_0S /* Set Software reset */ - -/* B0_LED 8 Bit LED register */ - /* Bit 7.. 2: reserved */ -#define LED_STAT_ON BIT_1S /* Status LED on */ -#define LED_STAT_OFF BIT_0S /* Status LED off */ - -/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ -#define PC_VAUX_ENA BIT_7 /* Switch VAUX Enable */ -#define PC_VAUX_DIS BIT_6 /* Switch VAUX Disable */ -#define PC_VCC_ENA BIT_5 /* Switch VCC Enable */ -#define PC_VCC_DIS BIT_4 /* Switch VCC Disable */ -#define PC_VAUX_ON BIT_3 /* Switch VAUX On */ -#define PC_VAUX_OFF BIT_2 /* Switch VAUX Off */ -#define PC_VCC_ON BIT_1 /* Switch VCC On */ -#define PC_VCC_OFF BIT_0 /* Switch VCC Off */ - -/* B0_ISRC 32 bit Interrupt Source Register */ -/* B0_IMSK 32 bit Interrupt Mask Register */ -/* B0_SP_ISRC 32 bit Special Interrupt Source Reg */ -/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ -#define IS_ALL_MSK 0xbfffffffUL /* All Interrupt bits */ -#define IS_HW_ERR BIT_31 /* Interrupt HW Error */ - /* Bit 30: reserved */ -#define IS_PA_TO_RX1 BIT_29 /* Packet Arb Timeout Rx1 */ -#define IS_PA_TO_RX2 BIT_28 /* Packet Arb Timeout Rx2 */ -#define IS_PA_TO_TX1 BIT_27 /* Packet Arb Timeout Tx1 */ -#define IS_PA_TO_TX2 BIT_26 /* Packet Arb Timeout Tx2 */ -#define IS_I2C_READY BIT_25 /* IRQ on end of I2C Tx */ -#define IS_IRQ_SW BIT_24 /* SW forced IRQ */ -#define IS_EXT_REG BIT_23 /* IRQ from LM80 or PHY (GENESIS only) */ - /* IRQ from PHY (YUKON only) */ -#define IS_TIMINT BIT_22 /* IRQ from Timer */ -#define IS_MAC1 BIT_21 /* IRQ from MAC 1 */ -#define IS_LNK_SYNC_M1 BIT_20 /* Link Sync Cnt wrap MAC 1 */ -#define IS_MAC2 BIT_19 /* IRQ from MAC 2 */ -#define IS_LNK_SYNC_M2 BIT_18 /* Link Sync Cnt wrap MAC 2 */ -/* Receive Queue 1 */ -#define IS_R1_B BIT_17 /* Q_R1 End of Buffer */ -#define IS_R1_F BIT_16 /* Q_R1 End of Frame */ -#define IS_R1_C BIT_15 /* Q_R1 Encoding Error */ -/* Receive Queue 2 */ -#define IS_R2_B BIT_14 /* Q_R2 End of Buffer */ -#define IS_R2_F BIT_13 /* Q_R2 End of Frame */ -#define IS_R2_C BIT_12 /* Q_R2 Encoding Error */ -/* Synchronous Transmit Queue 1 */ -#define IS_XS1_B BIT_11 /* Q_XS1 End of Buffer */ -#define IS_XS1_F BIT_10 /* Q_XS1 End of Frame */ -#define IS_XS1_C BIT_9 /* Q_XS1 Encoding Error */ -/* Asynchronous Transmit Queue 1 */ -#define IS_XA1_B BIT_8 /* Q_XA1 End of Buffer */ -#define IS_XA1_F BIT_7 /* Q_XA1 End of Frame */ -#define IS_XA1_C BIT_6 /* Q_XA1 Encoding Error */ -/* Synchronous Transmit Queue 2 */ -#define IS_XS2_B BIT_5 /* Q_XS2 End of Buffer */ -#define IS_XS2_F BIT_4 /* Q_XS2 End of Frame */ -#define IS_XS2_C BIT_3 /* Q_XS2 Encoding Error */ -/* Asynchronous Transmit Queue 2 */ -#define IS_XA2_B BIT_2 /* Q_XA2 End of Buffer */ -#define IS_XA2_F BIT_1 /* Q_XA2 End of Frame */ -#define IS_XA2_C BIT_0 /* Q_XA2 Encoding Error */ - - -/* B0_HWE_ISRC 32 bit HW Error Interrupt Src Reg */ -/* B0_HWE_IMSK 32 bit HW Error Interrupt Mask Reg */ -/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ -#define IS_ERR_MSK 0x00000fffL /* All Error bits */ - /* Bit 31..14: reserved */ -#define IS_IRQ_TIST_OV BIT_13 /* Time Stamp Timer Overflow (YUKON only) */ -#define IS_IRQ_SENSOR BIT_12 /* IRQ from Sensor (YUKON only) */ -#define IS_IRQ_MST_ERR BIT_11 /* IRQ master error detected */ -#define IS_IRQ_STAT BIT_10 /* IRQ status exception */ -#define IS_NO_STAT_M1 BIT_9 /* No Rx Status from MAC 1 */ -#define IS_NO_STAT_M2 BIT_8 /* No Rx Status from MAC 2 */ -#define IS_NO_TIST_M1 BIT_7 /* No Time Stamp from MAC 1 */ -#define IS_NO_TIST_M2 BIT_6 /* No Time Stamp from MAC 2 */ -#define IS_RAM_RD_PAR BIT_5 /* RAM Read Parity Error */ -#define IS_RAM_WR_PAR BIT_4 /* RAM Write Parity Error */ -#define IS_M1_PAR_ERR BIT_3 /* MAC 1 Parity Error */ -#define IS_M2_PAR_ERR BIT_2 /* MAC 2 Parity Error */ -#define IS_R1_PAR_ERR BIT_1 /* Queue R1 Parity Error */ -#define IS_R2_PAR_ERR BIT_0 /* Queue R2 Parity Error */ - -/* B2_CONN_TYP 8 bit Connector type */ -/* B2_PMD_TYP 8 bit PMD type */ -/* Values of connector and PMD type comply to SysKonnect internal std */ - -/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ -#define CFG_CHIP_R_MSK (0xf<<4) /* Bit 7.. 4: Chip Revision */ - /* Bit 3.. 2: reserved */ -#define CFG_DIS_M2_CLK BIT_1S /* Disable Clock for 2nd MAC */ -#define CFG_SNG_MAC BIT_0S /* MAC Config: 0=2 MACs / 1=1 MAC*/ - -/* B2_CHIP_ID 8 bit Chip Identification Number */ -#define CHIP_ID_GENESIS 0x0a /* Chip ID for GENESIS */ -#define CHIP_ID_YUKON 0xb0 /* Chip ID for YUKON */ -#define CHIP_ID_YUKON_LITE 0xb1 /* Chip ID for YUKON-Lite (Rev. A1-A3) */ -#define CHIP_ID_YUKON_LP 0xb2 /* Chip ID for YUKON-LP */ - -#define CHIP_REV_YU_LITE_A1 3 /* Chip Rev. for YUKON-Lite A1,A2 */ -#define CHIP_REV_YU_LITE_A3 7 /* Chip Rev. for YUKON-Lite A3 */ - -/* B2_FAR 32 bit Flash-Prom Addr Reg/Cnt */ -#define FAR_ADDR 0x1ffffL /* Bit 16.. 0: FPROM Address mask */ - -/* B2_LD_CTRL 8 bit EPROM loader control register */ -/* Bits are currently reserved */ - -/* B2_LD_TEST 8 bit EPROM loader test register */ - /* Bit 7.. 4: reserved */ -#define LD_T_ON BIT_3S /* Loader Test mode on */ -#define LD_T_OFF BIT_2S /* Loader Test mode off */ -#define LD_T_STEP BIT_1S /* Decrement FPROM addr. Counter */ -#define LD_START BIT_0S /* Start loading FPROM */ - -/* - * Timer Section - */ -/* B2_TI_CTRL 8 bit Timer control */ -/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ - /* Bit 7.. 3: reserved */ -#define TIM_START BIT_2S /* Start Timer */ -#define TIM_STOP BIT_1S /* Stop Timer */ -#define TIM_CLR_IRQ BIT_0S /* Clear Timer IRQ (!IRQM) */ - -/* B2_TI_TEST 8 Bit Timer Test */ -/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ -/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ - /* Bit 7.. 3: reserved */ -#define TIM_T_ON BIT_2S /* Test mode on */ -#define TIM_T_OFF BIT_1S /* Test mode off */ -#define TIM_T_STEP BIT_0S /* Test step */ - -/* B28_DPT_INI 32 bit Descriptor Poll Timer Init Val */ -/* B28_DPT_VAL 32 bit Descriptor Poll Timer Curr Val */ - /* Bit 31..24: reserved */ -#define DPT_MSK 0x00ffffffL /* Bit 23.. 0: Desc Poll Timer Bits */ - -/* B28_DPT_CTRL 8 bit Descriptor Poll Timer Ctrl Reg */ - /* Bit 7.. 2: reserved */ -#define DPT_START BIT_1S /* Start Descriptor Poll Timer */ -#define DPT_STOP BIT_0S /* Stop Descriptor Poll Timer */ - -/* B2_E_3 8 bit lower 4 bits used for HW self test result */ -#define B2_E3_RES_MASK 0x0f - -/* B2_TST_CTRL1 8 bit Test Control Register 1 */ -#define TST_FRC_DPERR_MR BIT_7S /* force DATAPERR on MST RD */ -#define TST_FRC_DPERR_MW BIT_6S /* force DATAPERR on MST WR */ -#define TST_FRC_DPERR_TR BIT_5S /* force DATAPERR on TRG RD */ -#define TST_FRC_DPERR_TW BIT_4S /* force DATAPERR on TRG WR */ -#define TST_FRC_APERR_M BIT_3S /* force ADDRPERR on MST */ -#define TST_FRC_APERR_T BIT_2S /* force ADDRPERR on TRG */ -#define TST_CFG_WRITE_ON BIT_1S /* Enable Config Reg WR */ -#define TST_CFG_WRITE_OFF BIT_0S /* Disable Config Reg WR */ - -/* B2_TST_CTRL2 8 bit Test Control Register 2 */ - /* Bit 7.. 4: reserved */ - /* force the following error on the next master read/write */ -#define TST_FRC_DPERR_MR64 BIT_3S /* DataPERR RD 64 */ -#define TST_FRC_DPERR_MW64 BIT_2S /* DataPERR WR 64 */ -#define TST_FRC_APERR_1M64 BIT_1S /* AddrPERR on 1. phase */ -#define TST_FRC_APERR_2M64 BIT_0S /* AddrPERR on 2. phase */ - -/* B2_GP_IO 32 bit General Purpose I/O Register */ - /* Bit 31..26: reserved */ -#define GP_DIR_9 BIT_25 /* IO_9 direct, 0=In/1=Out */ -#define GP_DIR_8 BIT_24 /* IO_8 direct, 0=In/1=Out */ -#define GP_DIR_7 BIT_23 /* IO_7 direct, 0=In/1=Out */ -#define GP_DIR_6 BIT_22 /* IO_6 direct, 0=In/1=Out */ -#define GP_DIR_5 BIT_21 /* IO_5 direct, 0=In/1=Out */ -#define GP_DIR_4 BIT_20 /* IO_4 direct, 0=In/1=Out */ -#define GP_DIR_3 BIT_19 /* IO_3 direct, 0=In/1=Out */ -#define GP_DIR_2 BIT_18 /* IO_2 direct, 0=In/1=Out */ -#define GP_DIR_1 BIT_17 /* IO_1 direct, 0=In/1=Out */ -#define GP_DIR_0 BIT_16 /* IO_0 direct, 0=In/1=Out */ - /* Bit 15..10: reserved */ -#define GP_IO_9 BIT_9 /* IO_9 pin */ -#define GP_IO_8 BIT_8 /* IO_8 pin */ -#define GP_IO_7 BIT_7 /* IO_7 pin */ -#define GP_IO_6 BIT_6 /* IO_6 pin */ -#define GP_IO_5 BIT_5 /* IO_5 pin */ -#define GP_IO_4 BIT_4 /* IO_4 pin */ -#define GP_IO_3 BIT_3 /* IO_3 pin */ -#define GP_IO_2 BIT_2 /* IO_2 pin */ -#define GP_IO_1 BIT_1 /* IO_1 pin */ -#define GP_IO_0 BIT_0 /* IO_0 pin */ - -/* B2_I2C_CTRL 32 bit I2C HW Control Register */ -#define I2C_FLAG BIT_31 /* Start read/write if WR */ -#define I2C_ADDR (0x7fffL<<16) /* Bit 30..16: Addr to be RD/WR */ -#define I2C_DEV_SEL (0x7fL<<9) /* Bit 15.. 9: I2C Device Select */ - /* Bit 8.. 5: reserved */ -#define I2C_BURST_LEN BIT_4 /* Burst Len, 1/4 bytes */ -#define I2C_DEV_SIZE (7<<1) /* Bit 3.. 1: I2C Device Size */ -#define I2C_025K_DEV (0<<1) /* 0: 256 Bytes or smal. */ -#define I2C_05K_DEV (1<<1) /* 1: 512 Bytes */ -#define I2C_1K_DEV (2<<1) /* 2: 1024 Bytes */ -#define I2C_2K_DEV (3<<1) /* 3: 2048 Bytes */ -#define I2C_4K_DEV (4<<1) /* 4: 4096 Bytes */ -#define I2C_8K_DEV (5<<1) /* 5: 8192 Bytes */ -#define I2C_16K_DEV (6<<1) /* 6: 16384 Bytes */ -#define I2C_32K_DEV (7<<1) /* 7: 32768 Bytes */ -#define I2C_STOP BIT_0 /* Interrupt I2C transfer */ - -/* B2_I2C_IRQ 32 bit I2C HW IRQ Register */ - /* Bit 31.. 1 reserved */ -#define I2C_CLR_IRQ BIT_0 /* Clear I2C IRQ */ - -/* B2_I2C_SW 32 bit (8 bit access) I2C HW SW Port Register */ - /* Bit 7.. 3: reserved */ -#define I2C_DATA_DIR BIT_2S /* direction of I2C_DATA */ -#define I2C_DATA BIT_1S /* I2C Data Port */ -#define I2C_CLK BIT_0S /* I2C Clock Port */ - -/* - * I2C Address - */ -#define I2C_SENS_ADDR LM80_ADDR /* I2C Sensor Address, (Volt and Temp)*/ - - -/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ - /* Bit 7.. 2: reserved */ -#define BSC_START BIT_1S /* Start Blink Source Counter */ -#define BSC_STOP BIT_0S /* Stop Blink Source Counter */ - -/* B2_BSC_STAT 8 bit Blink Source Counter Status */ - /* Bit 7.. 1: reserved */ -#define BSC_SRC BIT_0S /* Blink Source, 0=Off / 1=On */ - -/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ -#define BSC_T_ON BIT_2S /* Test mode on */ -#define BSC_T_OFF BIT_1S /* Test mode off */ -#define BSC_T_STEP BIT_0S /* Test step */ - - -/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ - /* Bit 31..19: reserved */ -#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ - -/* RAM Interface Registers */ -/* B3_RI_CTRL 16 bit RAM Iface Control Register */ - /* Bit 15..10: reserved */ -#define RI_CLR_RD_PERR BIT_9S /* Clear IRQ RAM Read Parity Err */ -#define RI_CLR_WR_PERR BIT_8S /* Clear IRQ RAM Write Parity Err*/ - /* Bit 7.. 2: reserved */ -#define RI_RST_CLR BIT_1S /* Clear RAM Interface Reset */ -#define RI_RST_SET BIT_0S /* Set RAM Interface Reset */ - -/* B3_RI_TEST 8 bit RAM Iface Test Register */ - /* Bit 15.. 4: reserved */ -#define RI_T_EV BIT_3S /* Timeout Event occured */ -#define RI_T_ON BIT_2S /* Timeout Timer Test On */ -#define RI_T_OFF BIT_1S /* Timeout Timer Test Off */ -#define RI_T_STEP BIT_0S /* Timeout Timer Step */ - -/* MAC Arbiter Registers */ -/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */ - /* Bit 15.. 4: reserved */ -#define MA_FOE_ON BIT_3S /* XMAC Fast Output Enable ON */ -#define MA_FOE_OFF BIT_2S /* XMAC Fast Output Enable OFF */ -#define MA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */ -#define MA_RST_SET BIT_0S /* Set MAC Arbiter Reset */ - -/* B3_MA_RC_CTRL 16 bit MAC Arbiter Recovery Ctrl Reg */ - /* Bit 15.. 8: reserved */ -#define MA_ENA_REC_TX2 BIT_7S /* Enable Recovery Timer TX2 */ -#define MA_DIS_REC_TX2 BIT_6S /* Disable Recovery Timer TX2 */ -#define MA_ENA_REC_TX1 BIT_5S /* Enable Recovery Timer TX1 */ -#define MA_DIS_REC_TX1 BIT_4S /* Disable Recovery Timer TX1 */ -#define MA_ENA_REC_RX2 BIT_3S /* Enable Recovery Timer RX2 */ -#define MA_DIS_REC_RX2 BIT_2S /* Disable Recovery Timer RX2 */ -#define MA_ENA_REC_RX1 BIT_1S /* Enable Recovery Timer RX1 */ -#define MA_DIS_REC_RX1 BIT_0S /* Disable Recovery Timer RX1 */ - -/* Packet Arbiter Registers */ -/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ - /* Bit 15..14: reserved */ -#define PA_CLR_TO_TX2 BIT_13S /* Clear IRQ Packet Timeout TX2 */ -#define PA_CLR_TO_TX1 BIT_12S /* Clear IRQ Packet Timeout TX1 */ -#define PA_CLR_TO_RX2 BIT_11S /* Clear IRQ Packet Timeout RX2 */ -#define PA_CLR_TO_RX1 BIT_10S /* Clear IRQ Packet Timeout RX1 */ -#define PA_ENA_TO_TX2 BIT_9S /* Enable Timeout Timer TX2 */ -#define PA_DIS_TO_TX2 BIT_8S /* Disable Timeout Timer TX2 */ -#define PA_ENA_TO_TX1 BIT_7S /* Enable Timeout Timer TX1 */ -#define PA_DIS_TO_TX1 BIT_6S /* Disable Timeout Timer TX1 */ -#define PA_ENA_TO_RX2 BIT_5S /* Enable Timeout Timer RX2 */ -#define PA_DIS_TO_RX2 BIT_4S /* Disable Timeout Timer RX2 */ -#define PA_ENA_TO_RX1 BIT_3S /* Enable Timeout Timer RX1 */ -#define PA_DIS_TO_RX1 BIT_2S /* Disable Timeout Timer RX1 */ -#define PA_RST_CLR BIT_1S /* Clear MAC Arbiter Reset */ -#define PA_RST_SET BIT_0S /* Set MAC Arbiter Reset */ - -#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\ - PA_ENA_TO_TX1 | PA_ENA_TO_TX2) - -/* Rx/Tx Path related Arbiter Test Registers */ -/* B3_MA_TO_TEST 16 bit MAC Arbiter Timeout Test Reg */ -/* B3_MA_RC_TEST 16 bit MAC Arbiter Recovery Test Reg */ -/* B3_PA_TEST 16 bit Packet Arbiter Test Register */ -/* Bit 15, 11, 7, and 3 are reserved in B3_PA_TEST */ -#define TX2_T_EV BIT_15S /* TX2 Timeout/Recv Event occured */ -#define TX2_T_ON BIT_14S /* TX2 Timeout/Recv Timer Test On */ -#define TX2_T_OFF BIT_13S /* TX2 Timeout/Recv Timer Tst Off */ -#define TX2_T_STEP BIT_12S /* TX2 Timeout/Recv Timer Step */ -#define TX1_T_EV BIT_11S /* TX1 Timeout/Recv Event occured */ -#define TX1_T_ON BIT_10S /* TX1 Timeout/Recv Timer Test On */ -#define TX1_T_OFF BIT_9S /* TX1 Timeout/Recv Timer Tst Off */ -#define TX1_T_STEP BIT_8S /* TX1 Timeout/Recv Timer Step */ -#define RX2_T_EV BIT_7S /* RX2 Timeout/Recv Event occured */ -#define RX2_T_ON BIT_6S /* RX2 Timeout/Recv Timer Test On */ -#define RX2_T_OFF BIT_5S /* RX2 Timeout/Recv Timer Tst Off */ -#define RX2_T_STEP BIT_4S /* RX2 Timeout/Recv Timer Step */ -#define RX1_T_EV BIT_3S /* RX1 Timeout/Recv Event occured */ -#define RX1_T_ON BIT_2S /* RX1 Timeout/Recv Timer Test On */ -#define RX1_T_OFF BIT_1S /* RX1 Timeout/Recv Timer Tst Off */ -#define RX1_T_STEP BIT_0S /* RX1 Timeout/Recv Timer Step */ - - -/* Transmit Arbiter Registers MAC 1 and 2, use MR_ADDR() to access */ -/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ -/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ -/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ -/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ - /* Bit 31..24: reserved */ -#define TXA_MAX_VAL 0x00ffffffUL/* Bit 23.. 0: Max TXA Timer/Cnt Val */ - -/* TXA_CTRL 8 bit Tx Arbiter Control Register */ -#define TXA_ENA_FSYNC BIT_7S /* Enable force of sync Tx queue */ -#define TXA_DIS_FSYNC BIT_6S /* Disable force of sync Tx queue */ -#define TXA_ENA_ALLOC BIT_5S /* Enable alloc of free bandwidth */ -#define TXA_DIS_ALLOC BIT_4S /* Disable alloc of free bandwidth */ -#define TXA_START_RC BIT_3S /* Start sync Rate Control */ -#define TXA_STOP_RC BIT_2S /* Stop sync Rate Control */ -#define TXA_ENA_ARB BIT_1S /* Enable Tx Arbiter */ -#define TXA_DIS_ARB BIT_0S /* Disable Tx Arbiter */ - -/* TXA_TEST 8 bit Tx Arbiter Test Register */ - /* Bit 7.. 6: reserved */ -#define TXA_INT_T_ON BIT_5S /* Tx Arb Interval Timer Test On */ -#define TXA_INT_T_OFF BIT_4S /* Tx Arb Interval Timer Test Off */ -#define TXA_INT_T_STEP BIT_3S /* Tx Arb Interval Timer Step */ -#define TXA_LIM_T_ON BIT_2S /* Tx Arb Limit Timer Test On */ -#define TXA_LIM_T_OFF BIT_1S /* Tx Arb Limit Timer Test Off */ -#define TXA_LIM_T_STEP BIT_0S /* Tx Arb Limit Timer Step */ - -/* TXA_STAT 8 bit Tx Arbiter Status Register */ - /* Bit 7.. 1: reserved */ -#define TXA_PRIO_XS BIT_0S /* sync queue has prio to send */ - -/* Q_BC 32 bit Current Byte Counter */ - /* Bit 31..16: reserved */ -#define BC_MAX 0xffff /* Bit 15.. 0: Byte counter */ - -/* BMU Control Status Registers */ -/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ -/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ -/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ -/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ -/* Q_CSR 32 bit BMU Control/Status Register */ - /* Bit 31..25: reserved */ -#define CSR_SV_IDLE BIT_24 /* BMU SM Idle */ - /* Bit 23..22: reserved */ -#define CSR_DESC_CLR BIT_21 /* Clear Reset for Descr */ -#define CSR_DESC_SET BIT_20 /* Set Reset for Descr */ -#define CSR_FIFO_CLR BIT_19 /* Clear Reset for FIFO */ -#define CSR_FIFO_SET BIT_18 /* Set Reset for FIFO */ -#define CSR_HPI_RUN BIT_17 /* Release HPI SM */ -#define CSR_HPI_RST BIT_16 /* Reset HPI SM to Idle */ -#define CSR_SV_RUN BIT_15 /* Release Supervisor SM */ -#define CSR_SV_RST BIT_14 /* Reset Supervisor SM */ -#define CSR_DREAD_RUN BIT_13 /* Release Descr Read SM */ -#define CSR_DREAD_RST BIT_12 /* Reset Descr Read SM */ -#define CSR_DWRITE_RUN BIT_11 /* Release Descr Write SM */ -#define CSR_DWRITE_RST BIT_10 /* Reset Descr Write SM */ -#define CSR_TRANS_RUN BIT_9 /* Release Transfer SM */ -#define CSR_TRANS_RST BIT_8 /* Reset Transfer SM */ -#define CSR_ENA_POL BIT_7 /* Enable Descr Polling */ -#define CSR_DIS_POL BIT_6 /* Disable Descr Polling */ -#define CSR_STOP BIT_5 /* Stop Rx/Tx Queue */ -#define CSR_START BIT_4 /* Start Rx/Tx Queue */ -#define CSR_IRQ_CL_P BIT_3 /* (Rx) Clear Parity IRQ */ -#define CSR_IRQ_CL_B BIT_2 /* Clear EOB IRQ */ -#define CSR_IRQ_CL_F BIT_1 /* Clear EOF IRQ */ -#define CSR_IRQ_CL_C BIT_0 /* Clear ERR IRQ */ - -#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\ - CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\ - CSR_TRANS_RST) -#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\ - CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ - CSR_TRANS_RUN) - -/* Q_F 32 bit Flag Register */ - /* Bit 31..28: reserved */ -#define F_ALM_FULL BIT_27 /* Rx FIFO: almost full */ -#define F_EMPTY BIT_27 /* Tx FIFO: empty flag */ -#define F_FIFO_EOF BIT_26 /* Tag (EOF Flag) bit in FIFO */ -#define F_WM_REACHED BIT_25 /* Watermark reached */ - /* reserved */ -#define F_FIFO_LEVEL (0x1fL<<16) /* Bit 23..16: # of Qwords in FIFO */ - /* Bit 15..11: reserved */ -#define F_WATER_MARK 0x0007ffL /* Bit 10.. 0: Watermark */ - -/* Q_T1 32 bit Test Register 1 */ -/* Holds four State Machine control Bytes */ -#define SM_CTRL_SV_MSK (0xffL<<24) /* Bit 31..24: Control Supervisor SM */ -#define SM_CTRL_RD_MSK (0xffL<<16) /* Bit 23..16: Control Read Desc SM */ -#define SM_CTRL_WR_MSK (0xffL<<8) /* Bit 15.. 8: Control Write Desc SM */ -#define SM_CTRL_TR_MSK 0xffL /* Bit 7.. 0: Control Transfer SM */ - -/* Q_T1_TR 8 bit Test Register 1 Transfer SM */ -/* Q_T1_WR 8 bit Test Register 1 Write Descriptor SM */ -/* Q_T1_RD 8 bit Test Register 1 Read Descriptor SM */ -/* Q_T1_SV 8 bit Test Register 1 Supervisor SM */ - -/* The control status byte of each machine looks like ... */ -#define SM_STATE 0xf0 /* Bit 7.. 4: State which shall be loaded */ -#define SM_LOAD BIT_3S /* Load the SM with SM_STATE */ -#define SM_TEST_ON BIT_2S /* Switch on SM Test Mode */ -#define SM_TEST_OFF BIT_1S /* Go off the Test Mode */ -#define SM_STEP BIT_0S /* Step the State Machine */ -/* The encoding of the states is not supported by the Diagnostics Tool */ - -/* Q_T2 32 bit Test Register 2 */ - /* Bit 31.. 8: reserved */ -#define T2_AC_T_ON BIT_7 /* Address Counter Test Mode on */ -#define T2_AC_T_OFF BIT_6 /* Address Counter Test Mode off */ -#define T2_BC_T_ON BIT_5 /* Byte Counter Test Mode on */ -#define T2_BC_T_OFF BIT_4 /* Byte Counter Test Mode off */ -#define T2_STEP04 BIT_3 /* Inc AC/Dec BC by 4 */ -#define T2_STEP03 BIT_2 /* Inc AC/Dec BC by 3 */ -#define T2_STEP02 BIT_1 /* Inc AC/Dec BC by 2 */ -#define T2_STEP01 BIT_0 /* Inc AC/Dec BC by 1 */ - -/* Q_T3 32 bit Test Register 3 */ - /* Bit 31.. 7: reserved */ -#define T3_MUX_MSK (7<<4) /* Bit 6.. 4: Mux Position */ - /* Bit 3: reserved */ -#define T3_VRAM_MSK 7 /* Bit 2.. 0: Virtual RAM Buffer Address */ - -/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ -/* RB_START 32 bit RAM Buffer Start Address */ -/* RB_END 32 bit RAM Buffer End Address */ -/* RB_WP 32 bit RAM Buffer Write Pointer */ -/* RB_RP 32 bit RAM Buffer Read Pointer */ -/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ -/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ -/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ -/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ -/* RB_PC 32 bit RAM Buffer Packet Counter */ -/* RB_LEV 32 bit RAM Buffer Level Register */ - /* Bit 31..19: reserved */ -#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ - -/* RB_TST2 8 bit RAM Buffer Test Register 2 */ - /* Bit 7.. 4: reserved */ -#define RB_PC_DEC BIT_3S /* Packet Counter Decrem */ -#define RB_PC_T_ON BIT_2S /* Packet Counter Test On */ -#define RB_PC_T_OFF BIT_1S /* Packet Counter Tst Off */ -#define RB_PC_INC BIT_0S /* Packet Counter Increm */ - -/* RB_TST1 8 bit RAM Buffer Test Register 1 */ - /* Bit 7: reserved */ -#define RB_WP_T_ON BIT_6S /* Write Pointer Test On */ -#define RB_WP_T_OFF BIT_5S /* Write Pointer Test Off */ -#define RB_WP_INC BIT_4S /* Write Pointer Increm */ - /* Bit 3: reserved */ -#define RB_RP_T_ON BIT_2S /* Read Pointer Test On */ -#define RB_RP_T_OFF BIT_1S /* Read Pointer Test Off */ -#define RB_RP_DEC BIT_0S /* Read Pointer Decrement */ - -/* RB_CTRL 8 bit RAM Buffer Control Register */ - /* Bit 7.. 6: reserved */ -#define RB_ENA_STFWD BIT_5S /* Enable Store & Forward */ -#define RB_DIS_STFWD BIT_4S /* Disable Store & Forward */ -#define RB_ENA_OP_MD BIT_3S /* Enable Operation Mode */ -#define RB_DIS_OP_MD BIT_2S /* Disable Operation Mode */ -#define RB_RST_CLR BIT_1S /* Clear RAM Buf STM Reset */ -#define RB_RST_SET BIT_0S /* Set RAM Buf STM Reset */ - - -/* Receive and Transmit MAC FIFO Registers (GENESIS only) */ - -/* RX_MFF_EA 32 bit Receive MAC FIFO End Address */ -/* RX_MFF_WP 32 bit Receive MAC FIFO Write Pointer */ -/* RX_MFF_RP 32 bit Receive MAC FIFO Read Pointer */ -/* RX_MFF_PC 32 bit Receive MAC FIFO Packet Counter */ -/* RX_MFF_LEV 32 bit Receive MAC FIFO Level */ -/* TX_MFF_EA 32 bit Transmit MAC FIFO End Address */ -/* TX_MFF_WP 32 bit Transmit MAC FIFO Write Pointer */ -/* TX_MFF_WSP 32 bit Transmit MAC FIFO WR Shadow Pointer */ -/* TX_MFF_RP 32 bit Transmit MAC FIFO Read Pointer */ -/* TX_MFF_PC 32 bit Transmit MAC FIFO Packet Cnt */ -/* TX_MFF_LEV 32 bit Transmit MAC FIFO Level */ - /* Bit 31.. 6: reserved */ -#define MFF_MSK 0x007fL /* Bit 5.. 0: MAC FIFO Address/Ptr Bits */ - -/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */ - /* Bit 15..14: reserved */ -#define MFF_ENA_RDY_PAT BIT_13S /* Enable Ready Patch */ -#define MFF_DIS_RDY_PAT BIT_12S /* Disable Ready Patch */ -#define MFF_ENA_TIM_PAT BIT_11S /* Enable Timing Patch */ -#define MFF_DIS_TIM_PAT BIT_10S /* Disable Timing Patch */ -#define MFF_ENA_ALM_FUL BIT_9S /* Enable AlmostFull Sign */ -#define MFF_DIS_ALM_FUL BIT_8S /* Disable AlmostFull Sign */ -#define MFF_ENA_PAUSE BIT_7S /* Enable Pause Signaling */ -#define MFF_DIS_PAUSE BIT_6S /* Disable Pause Signaling */ -#define MFF_ENA_FLUSH BIT_5S /* Enable Frame Flushing */ -#define MFF_DIS_FLUSH BIT_4S /* Disable Frame Flushing */ -#define MFF_ENA_TIST BIT_3S /* Enable Time Stamp Gener */ -#define MFF_DIS_TIST BIT_2S /* Disable Time Stamp Gener */ -#define MFF_CLR_INTIST BIT_1S /* Clear IRQ No Time Stamp */ -#define MFF_CLR_INSTAT BIT_0S /* Clear IRQ No Status */ - -#define MFF_RX_CTRL_DEF MFF_ENA_TIM_PAT - -/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */ -#define MFF_CLR_PERR BIT_15S /* Clear Parity Error IRQ */ - /* Bit 14: reserved */ -#define MFF_ENA_PKT_REC BIT_13S /* Enable Packet Recovery */ -#define MFF_DIS_PKT_REC BIT_12S /* Disable Packet Recovery */ -/* MFF_ENA_TIM_PAT (see RX_MFF_CTRL1) Bit 11: Enable Timing Patch */ -/* MFF_DIS_TIM_PAT (see RX_MFF_CTRL1) Bit 10: Disable Timing Patch */ -/* MFF_ENA_ALM_FUL (see RX_MFF_CTRL1) Bit 9: Enable Almost Full Sign */ -/* MFF_DIS_ALM_FUL (see RX_MFF_CTRL1) Bit 8: Disable Almost Full Sign */ -#define MFF_ENA_W4E BIT_7S /* Enable Wait for Empty */ -#define MFF_DIS_W4E BIT_6S /* Disable Wait for Empty */ -/* MFF_ENA_FLUSH (see RX_MFF_CTRL1) Bit 5: Enable Frame Flushing */ -/* MFF_DIS_FLUSH (see RX_MFF_CTRL1) Bit 4: Disable Frame Flushing */ -#define MFF_ENA_LOOPB BIT_3S /* Enable Loopback */ -#define MFF_DIS_LOOPB BIT_2S /* Disable Loopback */ -#define MFF_CLR_MAC_RST BIT_1S /* Clear XMAC Reset */ -#define MFF_SET_MAC_RST BIT_0S /* Set XMAC Reset */ - -#define MFF_TX_CTRL_DEF (MFF_ENA_PKT_REC | MFF_ENA_TIM_PAT | MFF_ENA_FLUSH) - -/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ -/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ - /* Bit 7: reserved */ -#define MFF_WSP_T_ON BIT_6S /* Tx: Write Shadow Ptr TestOn */ -#define MFF_WSP_T_OFF BIT_5S /* Tx: Write Shadow Ptr TstOff */ -#define MFF_WSP_INC BIT_4S /* Tx: Write Shadow Ptr Increment */ -#define MFF_PC_DEC BIT_3S /* Packet Counter Decrement */ -#define MFF_PC_T_ON BIT_2S /* Packet Counter Test On */ -#define MFF_PC_T_OFF BIT_1S /* Packet Counter Test Off */ -#define MFF_PC_INC BIT_0S /* Packet Counter Increment */ - -/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */ -/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */ - /* Bit 7: reserved */ -#define MFF_WP_T_ON BIT_6S /* Write Pointer Test On */ -#define MFF_WP_T_OFF BIT_5S /* Write Pointer Test Off */ -#define MFF_WP_INC BIT_4S /* Write Pointer Increm */ - /* Bit 3: reserved */ -#define MFF_RP_T_ON BIT_2S /* Read Pointer Test On */ -#define MFF_RP_T_OFF BIT_1S /* Read Pointer Test Off */ -#define MFF_RP_DEC BIT_0S /* Read Pointer Decrement */ - -/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */ -/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */ - /* Bit 7..4: reserved */ -#define MFF_ENA_OP_MD BIT_3S /* Enable Operation Mode */ -#define MFF_DIS_OP_MD BIT_2S /* Disable Operation Mode */ -#define MFF_RST_CLR BIT_1S /* Clear MAC FIFO Reset */ -#define MFF_RST_SET BIT_0S /* Set MAC FIFO Reset */ - - -/* Link LED Counter Registers (GENESIS only) */ - -/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */ -/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */ -/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */ - /* Bit 7.. 3: reserved */ -#define LED_START BIT_2S /* Start Timer */ -#define LED_STOP BIT_1S /* Stop Timer */ -#define LED_STATE BIT_0S /* Rx/Tx: LED State, 1=LED on */ -#define LED_CLR_IRQ BIT_0S /* Lnk: Clear Link IRQ */ - -/* RX_LED_TST 8 bit Receive LED Cnt Test Register */ -/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */ -/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */ - /* Bit 7.. 3: reserved */ -#define LED_T_ON BIT_2S /* LED Counter Test mode On */ -#define LED_T_OFF BIT_1S /* LED Counter Test mode Off */ -#define LED_T_STEP BIT_0S /* LED Counter Step */ - -/* LNK_LED_REG 8 bit Link LED Register */ - /* Bit 7.. 6: reserved */ -#define LED_BLK_ON BIT_5S /* Link LED Blinking On */ -#define LED_BLK_OFF BIT_4S /* Link LED Blinking Off */ -#define LED_SYNC_ON BIT_3S /* Use Sync Wire to switch LED */ -#define LED_SYNC_OFF BIT_2S /* Disable Sync Wire Input */ -#define LED_ON BIT_1S /* switch LED on */ -#define LED_OFF BIT_0S /* switch LED off */ - -/* Receive and Transmit GMAC FIFO Registers (YUKON only) */ - -/* RX_GMF_EA 32 bit Rx GMAC FIFO End Address */ -/* RX_GMF_AF_THR 32 bit Rx GMAC FIFO Almost Full Thresh. */ -/* RX_GMF_WP 32 bit Rx GMAC FIFO Write Pointer */ -/* RX_GMF_WLEV 32 bit Rx GMAC FIFO Write Level */ -/* RX_GMF_RP 32 bit Rx GMAC FIFO Read Pointer */ -/* RX_GMF_RLEV 32 bit Rx GMAC FIFO Read Level */ -/* TX_GMF_EA 32 bit Tx GMAC FIFO End Address */ -/* TX_GMF_AE_THR 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ -/* TX_GMF_WP 32 bit Tx GMAC FIFO Write Pointer */ -/* TX_GMF_WSP 32 bit Tx GMAC FIFO Write Shadow Ptr. */ -/* TX_GMF_WLEV 32 bit Tx GMAC FIFO Write Level */ -/* TX_GMF_RP 32 bit Tx GMAC FIFO Read Pointer */ -/* TX_GMF_RSTP 32 bit Tx GMAC FIFO Restart Pointer */ -/* TX_GMF_RLEV 32 bit Tx GMAC FIFO Read Level */ - -/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ - /* Bits 31..15: reserved */ -#define GMF_WP_TST_ON BIT_14 /* Write Pointer Test On */ -#define GMF_WP_TST_OFF BIT_13 /* Write Pointer Test Off */ -#define GMF_WP_STEP BIT_12 /* Write Pointer Step/Increment */ - /* Bit 11: reserved */ -#define GMF_RP_TST_ON BIT_10 /* Read Pointer Test On */ -#define GMF_RP_TST_OFF BIT_9 /* Read Pointer Test Off */ -#define GMF_RP_STEP BIT_8 /* Read Pointer Step/Increment */ -#define GMF_RX_F_FL_ON BIT_7 /* Rx FIFO Flush Mode On */ -#define GMF_RX_F_FL_OFF BIT_6 /* Rx FIFO Flush Mode Off */ -#define GMF_CLI_RX_FO BIT_5 /* Clear IRQ Rx FIFO Overrun */ -#define GMF_CLI_RX_FC BIT_4 /* Clear IRQ Rx Frame Complete */ -#define GMF_OPER_ON BIT_3 /* Operational Mode On */ -#define GMF_OPER_OFF BIT_2 /* Operational Mode Off */ -#define GMF_RST_CLR BIT_1 /* Clear GMAC FIFO Reset */ -#define GMF_RST_SET BIT_0 /* Set GMAC FIFO Reset */ - -/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ - /* Bits 31..19: reserved */ -#define GMF_WSP_TST_ON BIT_18 /* Write Shadow Pointer Test On */ -#define GMF_WSP_TST_OFF BIT_17 /* Write Shadow Pointer Test Off */ -#define GMF_WSP_STEP BIT_16 /* Write Shadow Pointer Step/Increment */ - /* Bits 15..7: same as for RX_GMF_CTRL_T */ -#define GMF_CLI_TX_FU BIT_6 /* Clear IRQ Tx FIFO Underrun */ -#define GMF_CLI_TX_FC BIT_5 /* Clear IRQ Tx Frame Complete */ -#define GMF_CLI_TX_PE BIT_4 /* Clear IRQ Tx Parity Error */ - /* Bits 3..0: same as for RX_GMF_CTRL_T */ - -#define GMF_RX_CTRL_DEF (GMF_OPER_ON | GMF_RX_F_FL_ON) -#define GMF_TX_CTRL_DEF GMF_OPER_ON - -#define RX_GMF_FL_THR_DEF 0x0a /* Rx GMAC FIFO Flush Threshold default */ - -/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ - /* Bit 7.. 3: reserved */ -#define GMT_ST_START BIT_2S /* Start Time Stamp Timer */ -#define GMT_ST_STOP BIT_1S /* Stop Time Stamp Timer */ -#define GMT_ST_CLR_IRQ BIT_0S /* Clear Time Stamp Timer IRQ */ - -/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ - /* Bits 31.. 8: reserved */ -#define GMC_H_BURST_ON BIT_7 /* Half Duplex Burst Mode On */ -#define GMC_H_BURST_OFF BIT_6 /* Half Duplex Burst Mode Off */ -#define GMC_F_LOOPB_ON BIT_5 /* FIFO Loopback On */ -#define GMC_F_LOOPB_OFF BIT_4 /* FIFO Loopback Off */ -#define GMC_PAUSE_ON BIT_3 /* Pause On */ -#define GMC_PAUSE_OFF BIT_2 /* Pause Off */ -#define GMC_RST_CLR BIT_1 /* Clear GMAC Reset */ -#define GMC_RST_SET BIT_0 /* Set GMAC Reset */ - -/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ - /* Bits 31..29: reserved */ -#define GPC_SEL_BDT BIT_28 /* Select Bi-Dir. Transfer for MDC/MDIO */ -#define GPC_INT_POL_HI BIT_27 /* IRQ Polarity is Active HIGH */ -#define GPC_75_OHM BIT_26 /* Use 75 Ohm Termination instead of 50 */ -#define GPC_DIS_FC BIT_25 /* Disable Automatic Fiber/Copper Detection */ -#define GPC_DIS_SLEEP BIT_24 /* Disable Energy Detect */ -#define GPC_HWCFG_M_3 BIT_23 /* HWCFG_MODE[3] */ -#define GPC_HWCFG_M_2 BIT_22 /* HWCFG_MODE[2] */ -#define GPC_HWCFG_M_1 BIT_21 /* HWCFG_MODE[1] */ -#define GPC_HWCFG_M_0 BIT_20 /* HWCFG_MODE[0] */ -#define GPC_ANEG_0 BIT_19 /* ANEG[0] */ -#define GPC_ENA_XC BIT_18 /* Enable MDI crossover */ -#define GPC_DIS_125 BIT_17 /* Disable 125 MHz clock */ -#define GPC_ANEG_3 BIT_16 /* ANEG[3] */ -#define GPC_ANEG_2 BIT_15 /* ANEG[2] */ -#define GPC_ANEG_1 BIT_14 /* ANEG[1] */ -#define GPC_ENA_PAUSE BIT_13 /* Enable Pause (SYM_OR_REM) */ -#define GPC_PHYADDR_4 BIT_12 /* Bit 4 of Phy Addr */ -#define GPC_PHYADDR_3 BIT_11 /* Bit 3 of Phy Addr */ -#define GPC_PHYADDR_2 BIT_10 /* Bit 2 of Phy Addr */ -#define GPC_PHYADDR_1 BIT_9 /* Bit 1 of Phy Addr */ -#define GPC_PHYADDR_0 BIT_8 /* Bit 0 of Phy Addr */ - /* Bits 7..2: reserved */ -#define GPC_RST_CLR BIT_1 /* Clear GPHY Reset */ -#define GPC_RST_SET BIT_0 /* Set GPHY Reset */ - -#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | \ - GPC_HWCFG_M_1 | GPC_HWCFG_M_0) - -#define GPC_HWCFG_GMII_FIB ( GPC_HWCFG_M_2 | \ - GPC_HWCFG_M_1 | GPC_HWCFG_M_0) - -#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | \ - GPC_ANEG_1 | GPC_ANEG_0) - -/* forced speed and duplex mode (don't mix with other ANEG bits) */ -#define GPC_FRC10MBIT_HALF 0 -#define GPC_FRC10MBIT_FULL GPC_ANEG_0 -#define GPC_FRC100MBIT_HALF GPC_ANEG_1 -#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1) - -/* auto-negotiation with limited advertised speeds */ -/* mix only with master/slave settings (for copper) */ -#define GPC_ADV_1000_HALF GPC_ANEG_2 -#define GPC_ADV_1000_FULL GPC_ANEG_3 -#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3) - -/* master/slave settings */ -/* only for copper with 1000 Mbps */ -#define GPC_FORCE_MASTER 0 -#define GPC_FORCE_SLAVE GPC_ANEG_0 -#define GPC_PREF_MASTER GPC_ANEG_1 -#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0) - -/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ -/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ -#define GM_IS_TX_CO_OV BIT_5 /* Transmit Counter Overflow IRQ */ -#define GM_IS_RX_CO_OV BIT_4 /* Receive Counter Overflow IRQ */ -#define GM_IS_TX_FF_UR BIT_3 /* Transmit FIFO Underrun */ -#define GM_IS_TX_COMPL BIT_2 /* Frame Transmission Complete */ -#define GM_IS_RX_FF_OR BIT_1 /* Receive FIFO Overrun */ -#define GM_IS_RX_COMPL BIT_0 /* Frame Reception Complete */ - -#define GMAC_DEF_MSK (GM_IS_TX_CO_OV | GM_IS_RX_CO_OV | \ - GM_IS_TX_FF_UR) - -/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ - /* Bits 15.. 2: reserved */ -#define GMLC_RST_CLR BIT_1S /* Clear GMAC Link Reset */ -#define GMLC_RST_SET BIT_0S /* Set GMAC Link Reset */ - - -/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ -#define WOL_CTL_LINK_CHG_OCC BIT_15S -#define WOL_CTL_MAGIC_PKT_OCC BIT_14S -#define WOL_CTL_PATTERN_OCC BIT_13S - -#define WOL_CTL_CLEAR_RESULT BIT_12S - -#define WOL_CTL_ENA_PME_ON_LINK_CHG BIT_11S -#define WOL_CTL_DIS_PME_ON_LINK_CHG BIT_10S -#define WOL_CTL_ENA_PME_ON_MAGIC_PKT BIT_9S -#define WOL_CTL_DIS_PME_ON_MAGIC_PKT BIT_8S -#define WOL_CTL_ENA_PME_ON_PATTERN BIT_7S -#define WOL_CTL_DIS_PME_ON_PATTERN BIT_6S - -#define WOL_CTL_ENA_LINK_CHG_UNIT BIT_5S -#define WOL_CTL_DIS_LINK_CHG_UNIT BIT_4S -#define WOL_CTL_ENA_MAGIC_PKT_UNIT BIT_3S -#define WOL_CTL_DIS_MAGIC_PKT_UNIT BIT_2S -#define WOL_CTL_ENA_PATTERN_UNIT BIT_1S -#define WOL_CTL_DIS_PATTERN_UNIT BIT_0S - -#define WOL_CTL_DEFAULT \ - (WOL_CTL_DIS_PME_ON_LINK_CHG | \ - WOL_CTL_DIS_PME_ON_PATTERN | \ - WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ - WOL_CTL_DIS_LINK_CHG_UNIT | \ - WOL_CTL_DIS_PATTERN_UNIT | \ - WOL_CTL_DIS_MAGIC_PKT_UNIT) - -/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ -#define WOL_CTL_PATT_ENA(x) (BIT_0 << (x)) - -#define SK_NUM_WOL_PATTERN 7 -#define SK_PATTERN_PER_WORD 4 -#define SK_BITMASK_PATTERN 7 -#define SK_POW_PATTERN_LENGTH 128 - -#define WOL_LENGTH_MSK 0x7f -#define WOL_LENGTH_SHIFT 8 - - -/* Receive and Transmit Descriptors ******************************************/ - -/* Transmit Descriptor struct */ -typedef struct s_HwTxd { - SK_U32 volatile TxCtrl; /* Transmit Buffer Control Field */ - SK_U32 TxNext; /* Physical Address Pointer to the next TxD */ - SK_U32 TxAdrLo; /* Physical Tx Buffer Address lower dword */ - SK_U32 TxAdrHi; /* Physical Tx Buffer Address upper dword */ - SK_U32 TxStat; /* Transmit Frame Status Word */ -#ifndef SK_USE_REV_DESC - SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ - SK_U16 TxRes1; /* 16 bit reserved field */ - SK_U16 TxTcpWp; /* TCP Checksum Write Position */ - SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ -#else /* SK_USE_REV_DESC */ - SK_U16 TxRes1; /* 16 bit reserved field */ - SK_U16 TxTcpOffs; /* TCP Checksum Calculation Start Value */ - SK_U16 TxTcpSp; /* TCP Checksum Calculation Start Position */ - SK_U16 TxTcpWp; /* TCP Checksum Write Position */ -#endif /* SK_USE_REV_DESC */ - SK_U32 TxRes2; /* 32 bit reserved field */ -} SK_HWTXD; - -/* Receive Descriptor struct */ -typedef struct s_HwRxd { - SK_U32 volatile RxCtrl; /* Receive Buffer Control Field */ - SK_U32 RxNext; /* Physical Address Pointer to the next RxD */ - SK_U32 RxAdrLo; /* Physical Rx Buffer Address lower dword */ - SK_U32 RxAdrHi; /* Physical Rx Buffer Address upper dword */ - SK_U32 RxStat; /* Receive Frame Status Word */ - SK_U32 RxTiSt; /* Receive Time Stamp (from XMAC on GENESIS) */ -#ifndef SK_USE_REV_DESC - SK_U16 RxTcpSum1; /* TCP Checksum 1 */ - SK_U16 RxTcpSum2; /* TCP Checksum 2 */ - SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ - SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ -#else /* SK_USE_REV_DESC */ - SK_U16 RxTcpSum2; /* TCP Checksum 2 */ - SK_U16 RxTcpSum1; /* TCP Checksum 1 */ - SK_U16 RxTcpSp2; /* TCP Checksum Calculation Start Position 2 */ - SK_U16 RxTcpSp1; /* TCP Checksum Calculation Start Position 1 */ -#endif /* SK_USE_REV_DESC */ -} SK_HWRXD; - -/* - * Drivers which use the reverse descriptor feature (PCI_OUR_REG_2) - * should set the define SK_USE_REV_DESC. - * Structures are 'normaly' not endianess dependent. But in - * this case the SK_U16 fields are bound to bit positions inside the - * descriptor. RxTcpSum1 e.g. must start at bit 0 within the 6.th DWord. - * The bit positions inside a DWord are of course endianess dependent and - * swaps if the DWord is swapped by the hardware. - */ - - -/* Descriptor Bit Definition */ -/* TxCtrl Transmit Buffer Control Field */ -/* RxCtrl Receive Buffer Control Field */ -#define BMU_OWN BIT_31 /* OWN bit: 0=host/1=BMU */ -#define BMU_STF BIT_30 /* Start of Frame */ -#define BMU_EOF BIT_29 /* End of Frame */ -#define BMU_IRQ_EOB BIT_28 /* Req "End of Buffer" IRQ */ -#define BMU_IRQ_EOF BIT_27 /* Req "End of Frame" IRQ */ -/* TxCtrl specific bits */ -#define BMU_STFWD BIT_26 /* (Tx) Store & Forward Frame */ -#define BMU_NO_FCS BIT_25 /* (Tx) Disable MAC FCS (CRC) generation */ -#define BMU_SW BIT_24 /* (Tx) 1 bit res. for SW use */ -/* RxCtrl specific bits */ -#define BMU_DEV_0 BIT_26 /* (Rx) Transfer data to Dev0 */ -#define BMU_STAT_VAL BIT_25 /* (Rx) Rx Status Valid */ -#define BMU_TIST_VAL BIT_24 /* (Rx) Rx TimeStamp Valid */ - /* Bit 23..16: BMU Check Opcodes */ -#define BMU_CHECK (0x55L<<16) /* Default BMU check */ -#define BMU_TCP_CHECK (0x56L<<16) /* Descr with TCP ext */ -#define BMU_UDP_CHECK (0x57L<<16) /* Descr with UDP ext (YUKON only) */ -#define BMU_BBC 0xffffL /* Bit 15.. 0: Buffer Byte Counter */ - -/* TxStat Transmit Frame Status Word */ -/* RxStat Receive Frame Status Word */ -/* - *Note: TxStat is reserved for ASIC loopback mode only - * - * The Bits of the Status words are defined in xmac_ii.h - * (see XMR_FS bits) - */ - -/* macros ********************************************************************/ - -/* Receive and Transmit Queues */ -#define Q_R1 0x0000 /* Receive Queue 1 */ -#define Q_R2 0x0080 /* Receive Queue 2 */ -#define Q_XS1 0x0200 /* Synchronous Transmit Queue 1 */ -#define Q_XA1 0x0280 /* Asynchronous Transmit Queue 1 */ -#define Q_XS2 0x0300 /* Synchronous Transmit Queue 2 */ -#define Q_XA2 0x0380 /* Asynchronous Transmit Queue 2 */ - -/* - * Macro Q_ADDR() - * - * Use this macro to access the Receive and Transmit Queue Registers. - * - * para: - * Queue Queue to access. - * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2 - * Offs Queue register offset. - * Values: Q_D, Q_DA_L ... Q_T2, Q_T3 - * - * usage SK_IN32(pAC, Q_ADDR(Q_R2, Q_BC), pVal) - */ -#define Q_ADDR(Queue, Offs) (B8_Q_REGS + (Queue) + (Offs)) - -/* - * Macro RB_ADDR() - * - * Use this macro to access the RAM Buffer Registers. - * - * para: - * Queue Queue to access. - * Values: Q_R1, Q_R2, Q_XS1, Q_XA1, Q_XS2, and Q_XA2 - * Offs Queue register offset. - * Values: RB_START, RB_END ... RB_LEV, RB_CTRL - * - * usage SK_IN32(pAC, RB_ADDR(Q_R2, RB_RP), pVal) - */ -#define RB_ADDR(Queue, Offs) (B16_RAM_REGS + (Queue) + (Offs)) - - -/* MAC Related Registers */ -#define MAC_1 0 /* belongs to the port near the slot */ -#define MAC_2 1 /* belongs to the port far away from the slot */ - -/* - * Macro MR_ADDR() - * - * Use this macro to access a MAC Related Registers inside the ASIC. - * - * para: - * Mac MAC to access. - * Values: MAC_1, MAC_2 - * Offs MAC register offset. - * Values: RX_MFF_EA, RX_MFF_WP ... LNK_LED_REG, - * TX_MFF_EA, TX_MFF_WP ... TX_LED_TST - * - * usage SK_IN32(pAC, MR_ADDR(MAC_1, TX_MFF_EA), pVal) - */ -#define MR_ADDR(Mac, Offs) (((Mac) << 7) + (Offs)) - -#ifdef SK_LITTLE_ENDIAN -#define XM_WORD_LO 0 -#define XM_WORD_HI 1 -#else /* !SK_LITTLE_ENDIAN */ -#define XM_WORD_LO 1 -#define XM_WORD_HI 0 -#endif /* !SK_LITTLE_ENDIAN */ - - -/* - * macros to access the XMAC (GENESIS only) - * - * XM_IN16(), to read a 16 bit register (e.g. XM_MMU_CMD) - * XM_OUT16(), to write a 16 bit register (e.g. XM_MMU_CMD) - * XM_IN32(), to read a 32 bit register (e.g. XM_TX_EV_CNT) - * XM_OUT32(), to write a 32 bit register (e.g. XM_TX_EV_CNT) - * XM_INADDR(), to read a network address register (e.g. XM_SRC_CHK) - * XM_OUTADDR(), to write a network address register (e.g. XM_SRC_CHK) - * XM_INHASH(), to read the XM_HSM_CHK register - * XM_OUTHASH() to write the XM_HSM_CHK register - * - * para: - * Mac XMAC to access values: MAC_1 or MAC_2 - * IoC I/O context needed for SK I/O macros - * Reg XMAC Register to read or write - * (p)Val Value or pointer to the value which should be read or written - * - * usage: XM_OUT16(IoC, MAC_1, XM_MMU_CMD, Value); - */ - -#define XMA(Mac, Reg) \ - ((BASE_XMAC_1 + (Mac) * (BASE_XMAC_2 - BASE_XMAC_1)) | ((Reg) << 1)) - -#define XM_IN16(IoC, Mac, Reg, pVal) \ - SK_IN16((IoC), XMA((Mac), (Reg)), (pVal)) - -#define XM_OUT16(IoC, Mac, Reg, Val) \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (Val)) - -#define XM_IN32(IoC, Mac, Reg, pVal) { \ - SK_IN16((IoC), XMA((Mac), (Reg)), \ - (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), \ - (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \ -} - -#define XM_OUT32(IoC, Mac, Reg, Val) { \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16)(((Val) >> 16) & 0xffffL));\ -} - -/* Remember: we are always writing to / reading from LITTLE ENDIAN memory */ - -#define XM_INADDR(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define XM_OUTADDR(IoC, Mac, Reg, pVal) { \ - SK_U8 SK_FAR *pByte; \ - pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff) | \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff) | \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff) | \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ -} - -#define XM_INHASH(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 SK_FAR *pByte; \ - pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ - SK_IN16((IoC), XMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+2)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+4)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), XMA((Mac), (Reg+6)), &Word); \ - pByte[6] = (SK_U8)(Word & 0x00ff); \ - pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define XM_OUTHASH(IoC, Mac, Reg, pVal) { \ - SK_U8 SK_FAR *pByte; \ - pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ - SK_OUT16((IoC), XMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff)| \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+2)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff)| \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff)| \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ - SK_OUT16((IoC), XMA((Mac), (Reg+6)), (SK_U16) \ - (((SK_U16)(pByte[6]) & 0x00ff)| \ - (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ -} - -/* - * macros to access the GMAC (YUKON only) - * - * GM_IN16(), to read a 16 bit register (e.g. GM_GP_STAT) - * GM_OUT16(), to write a 16 bit register (e.g. GM_GP_CTRL) - * GM_IN32(), to read a 32 bit register (e.g. GM_) - * GM_OUT32(), to write a 32 bit register (e.g. GM_) - * GM_INADDR(), to read a network address register (e.g. GM_SRC_ADDR_1L) - * GM_OUTADDR(), to write a network address register (e.g. GM_SRC_ADDR_2L) - * GM_INHASH(), to read the GM_MC_ADDR_H1 register - * GM_OUTHASH() to write the GM_MC_ADDR_H1 register - * - * para: - * Mac GMAC to access values: MAC_1 or MAC_2 - * IoC I/O context needed for SK I/O macros - * Reg GMAC Register to read or write - * (p)Val Value or pointer to the value which should be read or written - * - * usage: GM_OUT16(IoC, MAC_1, GM_GP_CTRL, Value); - */ - -#define GMA(Mac, Reg) \ - ((BASE_GMAC_1 + (Mac) * (BASE_GMAC_2 - BASE_GMAC_1)) | (Reg)) - -#define GM_IN16(IoC, Mac, Reg, pVal) \ - SK_IN16((IoC), GMA((Mac), (Reg)), (pVal)) - -#define GM_OUT16(IoC, Mac, Reg, Val) \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (Val)) - -#define GM_IN32(IoC, Mac, Reg, pVal) { \ - SK_IN16((IoC), GMA((Mac), (Reg)), \ - (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_LO]); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), \ - (SK_U16 SK_FAR*)&((SK_U16 SK_FAR*)(pVal))[XM_WORD_HI]); \ -} - -#define GM_OUT32(IoC, Mac, Reg, Val) { \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16)((Val) & 0xffffL)); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16)(((Val) >> 16) & 0xffffL));\ -} - -#define GM_INADDR(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define GM_OUTADDR(IoC, Mac, Reg, pVal) { \ - SK_U8 SK_FAR *pByte; \ - pByte = (SK_U8 SK_FAR *)&((SK_U8 SK_FAR *)(pVal))[0]; \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff) | \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff) | \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff) | \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ -} - -#define GM_INHASH(IoC, Mac, Reg, pVal) { \ - SK_U16 Word; \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_IN16((IoC), GMA((Mac), (Reg)), &Word); \ - pByte[0] = (SK_U8)(Word & 0x00ff); \ - pByte[1] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+4)), &Word); \ - pByte[2] = (SK_U8)(Word & 0x00ff); \ - pByte[3] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+8)), &Word); \ - pByte[4] = (SK_U8)(Word & 0x00ff); \ - pByte[5] = (SK_U8)((Word >> 8) & 0x00ff); \ - SK_IN16((IoC), GMA((Mac), (Reg+12)), &Word); \ - pByte[6] = (SK_U8)(Word & 0x00ff); \ - pByte[7] = (SK_U8)((Word >> 8) & 0x00ff); \ -} - -#define GM_OUTHASH(IoC, Mac, Reg, pVal) { \ - SK_U8 *pByte; \ - pByte = (SK_U8 *)&((SK_U8 *)(pVal))[0]; \ - SK_OUT16((IoC), GMA((Mac), (Reg)), (SK_U16) \ - (((SK_U16)(pByte[0]) & 0x00ff)| \ - (((SK_U16)(pByte[1]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+4)), (SK_U16) \ - (((SK_U16)(pByte[2]) & 0x00ff)| \ - (((SK_U16)(pByte[3]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+8)), (SK_U16) \ - (((SK_U16)(pByte[4]) & 0x00ff)| \ - (((SK_U16)(pByte[5]) << 8) & 0xff00))); \ - SK_OUT16((IoC), GMA((Mac), (Reg+12)), (SK_U16) \ - (((SK_U16)(pByte[6]) & 0x00ff)| \ - (((SK_U16)(pByte[7]) << 8) & 0xff00))); \ -} - -/* - * Different MAC Types - */ -#define SK_MAC_XMAC 0 /* Xaqti XMAC II */ -#define SK_MAC_GMAC 1 /* Marvell GMAC */ - -/* - * Different PHY Types - */ -#define SK_PHY_XMAC 0 /* integrated in XMAC II */ -#define SK_PHY_BCOM 1 /* Broadcom BCM5400 */ -#define SK_PHY_LONE 2 /* Level One LXT1000 */ -#define SK_PHY_NAT 3 /* National DP83891 */ -#define SK_PHY_MARV_COPPER 4 /* Marvell 88E1011S */ -#define SK_PHY_MARV_FIBER 5 /* Marvell 88E1011S working on fiber */ - -/* - * PHY addresses (bits 12..8 of PHY address reg) - */ -#define PHY_ADDR_XMAC (0<<8) -#define PHY_ADDR_BCOM (1<<8) -#define PHY_ADDR_LONE (3<<8) -#define PHY_ADDR_NAT (0<<8) - -/* GPHY address (bits 15..11 of SMI control reg) */ -#define PHY_ADDR_MARV 0 - -/* - * macros to access the PHY - * - * PHY_READ() read a 16 bit value from the PHY - * PHY_WRITE() write a 16 bit value to the PHY - * - * para: - * IoC I/O context needed for SK I/O macros - * pPort Pointer to port struct for PhyAddr - * Mac XMAC to access values: MAC_1 or MAC_2 - * PhyReg PHY Register to read or write - * (p)Val Value or pointer to the value which should be read or - * written. - * - * usage: PHY_READ(IoC, pPort, MAC_1, PHY_CTRL, Value); - * Warning: a PHY_READ on an uninitialized PHY (PHY still in reset) never - * comes back. This is checked in DEBUG mode. - */ -#ifndef DEBUG -#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ - SK_U16 Mmu; \ - \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - } \ -} -#else -#define PHY_READ(IoC, pPort, Mac, PhyReg, pVal) { \ - SK_U16 Mmu; \ - int __i = 0; \ - \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - __i++; \ - if (__i > 100000) { \ - SK_DBG_PRINTF("*****************************\n"); \ - SK_DBG_PRINTF("PHY_READ on uninitialized PHY\n"); \ - SK_DBG_PRINTF("*****************************\n"); \ - break; \ - } \ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); \ - XM_IN16((IoC), (Mac), XM_PHY_DATA, (pVal)); \ - } \ -} -#endif /* DEBUG */ - -#define PHY_WRITE(IoC, pPort, Mac, PhyReg, Val) { \ - SK_U16 Mmu; \ - \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ - } \ - XM_OUT16((IoC), (Mac), XM_PHY_ADDR, (PhyReg) | (pPort)->PhyAddr); \ - XM_OUT16((IoC), (Mac), XM_PHY_DATA, (Val)); \ - if ((pPort)->PhyType != SK_PHY_XMAC) { \ - do { \ - XM_IN16((IoC), (Mac), XM_MMU_CMD, &Mmu); \ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); \ - } \ -} - -/* - * Macro PCI_C() - * - * Use this macro to access PCI config register from the I/O space. - * - * para: - * Addr PCI configuration register to access. - * Values: PCI_VENDOR_ID ... PCI_VPD_ADR_REG, - * - * usage SK_IN16(pAC, PCI_C(PCI_VENDOR_ID), pVal); - */ -#define PCI_C(Addr) (B7_CFG_SPC + (Addr)) /* PCI Config Space */ - -/* - * Macro SK_HW_ADDR(Base, Addr) - * - * Calculates the effective HW address - * - * para: - * Base I/O or memory base address - * Addr Address offset - * - * usage: May be used in SK_INxx and SK_OUTxx macros - * #define SK_IN8(pAC, Addr, pVal) ...\ - * *pVal = (SK_U8)inp(SK_HW_ADDR(pAC->Hw.Iop, Addr))) - */ -#ifdef SK_MEM_MAPPED_IO -#define SK_HW_ADDR(Base, Addr) ((Base) + (Addr)) -#else /* SK_MEM_MAPPED_IO */ -#define SK_HW_ADDR(Base, Addr) \ - ((Base) + (((Addr) & 0x7f) | (((Addr) >> 7 > 0) ? 0x80 : 0))) -#endif /* SK_MEM_MAPPED_IO */ - -#define SZ_LONG (sizeof(SK_U32)) - -/* - * Macro SK_HWAC_LINK_LED() - * - * Use this macro to set the link LED mode. - * para: - * pAC Pointer to adapter context struct - * IoC I/O context needed for SK I/O macros - * Port Port number - * Mode Mode to set for this LED - */ -#define SK_HWAC_LINK_LED(pAC, IoC, Port, Mode) \ - SK_OUT8(IoC, MR_ADDR(Port, LNK_LED_REG), Mode); - - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKGEHW_H */ diff --git a/drivers/net/sk98lin/h/skgehwt.h b/drivers/net/sk98lin/h/skgehwt.h deleted file mode 100644 index e6b0016a695c..000000000000 --- a/drivers/net/sk98lin/h/skgehwt.h +++ /dev/null @@ -1,48 +0,0 @@ -/****************************************************************************** - * - * Name: skhwt.h - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.7 $ - * Date: $Date: 2003/09/16 12:55:08 $ - * Purpose: Defines for the hardware timer functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKGEHWT.H contains all defines and types for the timer functions - */ - -#ifndef _SKGEHWT_H_ -#define _SKGEHWT_H_ - -/* - * SK Hardware Timer - * - needed wherever the HWT module is used - * - use in Adapters context name pAC->Hwt - */ -typedef struct s_Hwt { - SK_U32 TStart; /* HWT start */ - SK_U32 TStop; /* HWT stop */ - int TActive; /* HWT: flag : active/inactive */ -} SK_HWT; - -extern void SkHwtInit(SK_AC *pAC, SK_IOC Ioc); -extern void SkHwtStart(SK_AC *pAC, SK_IOC Ioc, SK_U32 Time); -extern void SkHwtStop(SK_AC *pAC, SK_IOC Ioc); -extern SK_U32 SkHwtRead(SK_AC *pAC, SK_IOC Ioc); -extern void SkHwtIsr(SK_AC *pAC, SK_IOC Ioc); -#endif /* _SKGEHWT_H_ */ diff --git a/drivers/net/sk98lin/h/skgei2c.h b/drivers/net/sk98lin/h/skgei2c.h deleted file mode 100644 index d9b6f6d8dfe2..000000000000 --- a/drivers/net/sk98lin/h/skgei2c.h +++ /dev/null @@ -1,210 +0,0 @@ -/****************************************************************************** - * - * Name: skgei2c.h - * Project: Gigabit Ethernet Adapters, TWSI-Module - * Version: $Revision: 1.25 $ - * Date: $Date: 2003/10/20 09:06:05 $ - * Purpose: Special defines for TWSI - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKGEI2C.H contains all SK-98xx specific defines for the TWSI handling - */ - -#ifndef _INC_SKGEI2C_H_ -#define _INC_SKGEI2C_H_ - -/* - * Macros to access the B2_I2C_CTRL - */ -#define SK_I2C_CTL(IoC, flag, dev, dev_size, reg, burst) \ - SK_OUT32(IoC, B2_I2C_CTRL,\ - (flag ? 0x80000000UL : 0x0L) | \ - (((SK_U32)reg << 16) & I2C_ADDR) | \ - (((SK_U32)dev << 9) & I2C_DEV_SEL) | \ - (dev_size & I2C_DEV_SIZE) | \ - ((burst << 4) & I2C_BURST_LEN)) - -#define SK_I2C_STOP(IoC) { \ - SK_U32 I2cCtrl; \ - SK_IN32(IoC, B2_I2C_CTRL, &I2cCtrl); \ - SK_OUT32(IoC, B2_I2C_CTRL, I2cCtrl | I2C_STOP); \ -} - -#define SK_I2C_GET_CTL(IoC, pI2cCtrl) SK_IN32(IoC, B2_I2C_CTRL, pI2cCtrl) - -/* - * Macros to access the TWSI SW Registers - */ -#define SK_I2C_SET_BIT(IoC, SetBits) { \ - SK_U8 OrgBits; \ - SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ - SK_OUT8(IoC, B2_I2C_SW, OrgBits | (SK_U8)(SetBits)); \ -} - -#define SK_I2C_CLR_BIT(IoC, ClrBits) { \ - SK_U8 OrgBits; \ - SK_IN8(IoC, B2_I2C_SW, &OrgBits); \ - SK_OUT8(IoC, B2_I2C_SW, OrgBits & ~((SK_U8)(ClrBits))); \ -} - -#define SK_I2C_GET_SW(IoC, pI2cSw) SK_IN8(IoC, B2_I2C_SW, pI2cSw) - -/* - * define the possible sensor states - */ -#define SK_SEN_IDLE 0 /* Idle: sensor not read */ -#define SK_SEN_VALUE 1 /* Value Read cycle */ -#define SK_SEN_VALEXT 2 /* Extended Value Read cycle */ - -/* - * Conversion factor to convert read Voltage sensor to milli Volt - * Conversion factor to convert read Temperature sensor to 10th degree Celsius - */ -#define SK_LM80_VT_LSB 22 /* 22mV LSB resolution */ -#define SK_LM80_TEMP_LSB 10 /* 1 degree LSB resolution */ -#define SK_LM80_TEMPEXT_LSB 5 /* 0.5 degree LSB resolution for ext. val. */ - -/* - * formula: counter = (22500*60)/(rpm * divisor * pulses/2) - * assuming: 6500rpm, 4 pulses, divisor 1 - */ -#define SK_LM80_FAN_FAKTOR ((22500L*60)/(1*2)) - -/* - * Define sensor management data - * Maximum is reached on Genesis copper dual port and Yukon-64 - * Board specific maximum is in pAC->I2c.MaxSens - */ -#define SK_MAX_SENSORS 8 /* maximal no. of installed sensors */ -#define SK_MIN_SENSORS 5 /* minimal no. of installed sensors */ - -/* - * To watch the state machine (SM) use the timer in two ways - * instead of one as hitherto - */ -#define SK_TIMER_WATCH_SM 0 /* Watch the SM to finish in a spec. time */ -#define SK_TIMER_NEW_GAUGING 1 /* Start a new gauging when timer expires */ - -/* - * Defines for the individual thresholds - */ - -/* Temperature sensor */ -#define SK_SEN_TEMP_HIGH_ERR 800 /* Temperature High Err Threshold */ -#define SK_SEN_TEMP_HIGH_WARN 700 /* Temperature High Warn Threshold */ -#define SK_SEN_TEMP_LOW_WARN 100 /* Temperature Low Warn Threshold */ -#define SK_SEN_TEMP_LOW_ERR 0 /* Temperature Low Err Threshold */ - -/* VCC which should be 5 V */ -#define SK_SEN_PCI_5V_HIGH_ERR 5588 /* Voltage PCI High Err Threshold */ -#define SK_SEN_PCI_5V_HIGH_WARN 5346 /* Voltage PCI High Warn Threshold */ -#define SK_SEN_PCI_5V_LOW_WARN 4664 /* Voltage PCI Low Warn Threshold */ -#define SK_SEN_PCI_5V_LOW_ERR 4422 /* Voltage PCI Low Err Threshold */ - -/* - * VIO may be 5 V or 3.3 V. Initialization takes two parts: - * 1. Initialize lowest lower limit and highest higher limit. - * 2. After the first value is read correct the upper or the lower limit to - * the appropriate C constant. - * - * Warning limits are +-5% of the exepected voltage. - * Error limits are +-10% of the expected voltage. - */ - -/* Bug fix AF: 16.Aug.2001: Correct the init base of LM80 sensor */ - -#define SK_SEN_PCI_IO_5V_HIGH_ERR 5566 /* + 10% V PCI-IO High Err Threshold */ -#define SK_SEN_PCI_IO_5V_HIGH_WARN 5324 /* + 5% V PCI-IO High Warn Threshold */ - /* 5000 mVolt */ -#define SK_SEN_PCI_IO_5V_LOW_WARN 4686 /* - 5% V PCI-IO Low Warn Threshold */ -#define SK_SEN_PCI_IO_5V_LOW_ERR 4444 /* - 10% V PCI-IO Low Err Threshold */ - -#define SK_SEN_PCI_IO_RANGE_LIMITER 4000 /* 4000 mV range delimiter */ - -/* correction values for the second pass */ -#define SK_SEN_PCI_IO_3V3_HIGH_ERR 3850 /* + 15% V PCI-IO High Err Threshold */ -#define SK_SEN_PCI_IO_3V3_HIGH_WARN 3674 /* + 10% V PCI-IO High Warn Threshold */ - /* 3300 mVolt */ -#define SK_SEN_PCI_IO_3V3_LOW_WARN 2926 /* - 10% V PCI-IO Low Warn Threshold */ -#define SK_SEN_PCI_IO_3V3_LOW_ERR 2772 /* - 15% V PCI-IO Low Err Threshold */ - -/* - * VDD voltage - */ -#define SK_SEN_VDD_HIGH_ERR 3630 /* Voltage ASIC High Err Threshold */ -#define SK_SEN_VDD_HIGH_WARN 3476 /* Voltage ASIC High Warn Threshold */ -#define SK_SEN_VDD_LOW_WARN 3146 /* Voltage ASIC Low Warn Threshold */ -#define SK_SEN_VDD_LOW_ERR 2970 /* Voltage ASIC Low Err Threshold */ - -/* - * PHY PLL 3V3 voltage - */ -#define SK_SEN_PLL_3V3_HIGH_ERR 3630 /* Voltage PMA High Err Threshold */ -#define SK_SEN_PLL_3V3_HIGH_WARN 3476 /* Voltage PMA High Warn Threshold */ -#define SK_SEN_PLL_3V3_LOW_WARN 3146 /* Voltage PMA Low Warn Threshold */ -#define SK_SEN_PLL_3V3_LOW_ERR 2970 /* Voltage PMA Low Err Threshold */ - -/* - * VAUX (YUKON only) - */ -#define SK_SEN_VAUX_3V3_HIGH_ERR 3630 /* Voltage VAUX High Err Threshold */ -#define SK_SEN_VAUX_3V3_HIGH_WARN 3476 /* Voltage VAUX High Warn Threshold */ -#define SK_SEN_VAUX_3V3_LOW_WARN 3146 /* Voltage VAUX Low Warn Threshold */ -#define SK_SEN_VAUX_3V3_LOW_ERR 2970 /* Voltage VAUX Low Err Threshold */ -#define SK_SEN_VAUX_0V_WARN_ERR 0 /* if VAUX not present */ -#define SK_SEN_VAUX_RANGE_LIMITER 1000 /* 1000 mV range delimiter */ - -/* - * PHY 2V5 voltage - */ -#define SK_SEN_PHY_2V5_HIGH_ERR 2750 /* Voltage PHY High Err Threshold */ -#define SK_SEN_PHY_2V5_HIGH_WARN 2640 /* Voltage PHY High Warn Threshold */ -#define SK_SEN_PHY_2V5_LOW_WARN 2376 /* Voltage PHY Low Warn Threshold */ -#define SK_SEN_PHY_2V5_LOW_ERR 2222 /* Voltage PHY Low Err Threshold */ - -/* - * ASIC Core 1V5 voltage (YUKON only) - */ -#define SK_SEN_CORE_1V5_HIGH_ERR 1650 /* Voltage ASIC Core High Err Threshold */ -#define SK_SEN_CORE_1V5_HIGH_WARN 1575 /* Voltage ASIC Core High Warn Threshold */ -#define SK_SEN_CORE_1V5_LOW_WARN 1425 /* Voltage ASIC Core Low Warn Threshold */ -#define SK_SEN_CORE_1V5_LOW_ERR 1350 /* Voltage ASIC Core Low Err Threshold */ - -/* - * FAN 1 speed - */ -/* assuming: 6500rpm +-15%, 4 pulses, - * warning at: 80 % - * error at: 70 % - * no upper limit - */ -#define SK_SEN_FAN_HIGH_ERR 20000 /* FAN Speed High Err Threshold */ -#define SK_SEN_FAN_HIGH_WARN 20000 /* FAN Speed High Warn Threshold */ -#define SK_SEN_FAN_LOW_WARN 5200 /* FAN Speed Low Warn Threshold */ -#define SK_SEN_FAN_LOW_ERR 4550 /* FAN Speed Low Err Threshold */ - -/* - * Some Voltages need dynamic thresholds - */ -#define SK_SEN_DYN_INIT_NONE 0 /* No dynamic init of thresholds */ -#define SK_SEN_DYN_INIT_PCI_IO 10 /* Init PCI-IO with new thresholds */ -#define SK_SEN_DYN_INIT_VAUX 11 /* Init VAUX with new thresholds */ - -extern int SkLm80ReadSensor(SK_AC *pAC, SK_IOC IoC, SK_SENSOR *pSen); -#endif /* n_INC_SKGEI2C_H */ diff --git a/drivers/net/sk98lin/h/skgeinit.h b/drivers/net/sk98lin/h/skgeinit.h deleted file mode 100644 index 143e635ec24d..000000000000 --- a/drivers/net/sk98lin/h/skgeinit.h +++ /dev/null @@ -1,797 +0,0 @@ -/****************************************************************************** - * - * Name: skgeinit.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.83 $ - * Date: $Date: 2003/09/16 14:07:37 $ - * Purpose: Structures and prototypes for the GE Init Module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_SKGEINIT_H_ -#define __INC_SKGEINIT_H_ - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -#define SK_TEST_VAL 0x11335577UL - -/* modifying Link LED behaviour (used with SkGeLinkLED()) */ -#define SK_LNK_OFF LED_OFF -#define SK_LNK_ON (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) -#define SK_LNK_BLINK (LED_ON | LED_BLK_ON | LED_SYNC_ON) -#define SK_LNK_PERM (LED_ON | LED_BLK_OFF | LED_SYNC_ON) -#define SK_LNK_TST (LED_ON | LED_BLK_ON | LED_SYNC_OFF) - -/* parameter 'Mode' when calling SK_HWAC_LINK_LED() */ -#define SK_LED_OFF LED_OFF -#define SK_LED_ACTIVE (LED_ON | LED_BLK_OFF | LED_SYNC_OFF) -#define SK_LED_STANDBY (LED_ON | LED_BLK_ON | LED_SYNC_OFF) - -/* addressing LED Registers in SkGeXmitLED() */ -#define XMIT_LED_INI 0 -#define XMIT_LED_CNT (RX_LED_VAL - RX_LED_INI) -#define XMIT_LED_CTRL (RX_LED_CTRL- RX_LED_INI) -#define XMIT_LED_TST (RX_LED_TST - RX_LED_INI) - -/* parameter 'Mode' when calling SkGeXmitLED() */ -#define SK_LED_DIS 0 -#define SK_LED_ENA 1 -#define SK_LED_TST 2 - -/* Counter and Timer constants, for a host clock of 62.5 MHz */ -#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */ -#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */ - -#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */ - -#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */ - /* 215 ms at 78.12 MHz */ - -#define SK_FACT_62 100 /* is given in percent */ -#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ -#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */ - -/* Timeout values */ -#define SK_MAC_TO_53 72 /* MAC arbiter timeout */ -#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */ -#define SK_PKT_TO_MAX 0xffff /* Maximum value */ -#define SK_RI_TO_53 36 /* RAM interface timeout */ - -#define SK_PHY_ACC_TO 600000 /* PHY access timeout */ - -/* RAM Buffer High Pause Threshold values */ -#define SK_RB_ULPP ( 8 * 1024) /* Upper Level in kB/8 */ -#define SK_RB_LLPP_S (10 * 1024) /* Lower Level for small Queues */ -#define SK_RB_LLPP_B (16 * 1024) /* Lower Level for big Queues */ - -#ifndef SK_BMU_RX_WM -#define SK_BMU_RX_WM 0x600 /* BMU Rx Watermark */ -#endif -#ifndef SK_BMU_TX_WM -#define SK_BMU_TX_WM 0x600 /* BMU Tx Watermark */ -#endif - -/* XMAC II Rx High Watermark */ -#define SK_XM_RX_HI_WM 0x05aa /* 1450 */ - -/* XMAC II Tx Threshold */ -#define SK_XM_THR_REDL 0x01fb /* .. for redundant link usage */ -#define SK_XM_THR_SL 0x01fb /* .. for single link adapters */ -#define SK_XM_THR_MULL 0x01fb /* .. for multiple link usage */ -#define SK_XM_THR_JUMBO 0x03fc /* .. for jumbo frame usage */ - -/* values for GIPortUsage */ -#define SK_RED_LINK 1 /* redundant link usage */ -#define SK_MUL_LINK 2 /* multiple link usage */ -#define SK_JUMBO_LINK 3 /* driver uses jumbo frames */ - -/* Minimum RAM Buffer Rx Queue Size */ -#define SK_MIN_RXQ_SIZE 16 /* 16 kB */ - -/* Minimum RAM Buffer Tx Queue Size */ -#define SK_MIN_TXQ_SIZE 16 /* 16 kB */ - -/* Queue Size units */ -#define QZ_UNITS 0x7 -#define QZ_STEP 8 - -/* Percentage of queue size from whole memory */ -/* 80 % for receive */ -#define RAM_QUOTA_RX 80L -/* 0% for sync transfer */ -#define RAM_QUOTA_SYNC 0L -/* the rest (20%) is taken for async transfer */ - -/* Get the rounded queue size in Bytes in 8k steps */ -#define ROUND_QUEUE_SIZE(SizeInBytes) \ - ((((unsigned long) (SizeInBytes) + (QZ_STEP*1024L)-1) / 1024) & \ - ~(QZ_STEP-1)) - -/* Get the rounded queue size in KBytes in 8k steps */ -#define ROUND_QUEUE_SIZE_KB(Kilobytes) \ - ROUND_QUEUE_SIZE((Kilobytes) * 1024L) - -/* Types of RAM Buffer Queues */ -#define SK_RX_SRAM_Q 1 /* small receive queue */ -#define SK_RX_BRAM_Q 2 /* big receive queue */ -#define SK_TX_RAM_Q 3 /* small or big transmit queue */ - -/* parameter 'Dir' when calling SkGeStopPort() */ -#define SK_STOP_TX 1 /* Stops the transmit path, resets the XMAC */ -#define SK_STOP_RX 2 /* Stops the receive path */ -#define SK_STOP_ALL 3 /* Stops Rx and Tx path, resets the XMAC */ - -/* parameter 'RstMode' when calling SkGeStopPort() */ -#define SK_SOFT_RST 1 /* perform a software reset */ -#define SK_HARD_RST 2 /* perform a hardware reset */ - -/* Init Levels */ -#define SK_INIT_DATA 0 /* Init level 0: init data structures */ -#define SK_INIT_IO 1 /* Init level 1: init with IOs */ -#define SK_INIT_RUN 2 /* Init level 2: init for run time */ - -/* Link Mode Parameter */ -#define SK_LMODE_HALF 1 /* Half Duplex Mode */ -#define SK_LMODE_FULL 2 /* Full Duplex Mode */ -#define SK_LMODE_AUTOHALF 3 /* AutoHalf Duplex Mode */ -#define SK_LMODE_AUTOFULL 4 /* AutoFull Duplex Mode */ -#define SK_LMODE_AUTOBOTH 5 /* AutoBoth Duplex Mode */ -#define SK_LMODE_AUTOSENSE 6 /* configured mode auto sensing */ -#define SK_LMODE_INDETERMINATED 7 /* indeterminated */ - -/* Auto-negotiation timeout in 100ms granularity */ -#define SK_AND_MAX_TO 6 /* Wait 600 msec before link comes up */ - -/* Auto-negotiation error codes */ -#define SK_AND_OK 0 /* no error */ -#define SK_AND_OTHER 1 /* other error than below */ -#define SK_AND_DUP_CAP 2 /* Duplex capabilities error */ - - -/* Link Speed Capabilities */ -#define SK_LSPEED_CAP_AUTO (1<<0) /* Automatic resolution */ -#define SK_LSPEED_CAP_10MBPS (1<<1) /* 10 Mbps */ -#define SK_LSPEED_CAP_100MBPS (1<<2) /* 100 Mbps */ -#define SK_LSPEED_CAP_1000MBPS (1<<3) /* 1000 Mbps */ -#define SK_LSPEED_CAP_INDETERMINATED (1<<4) /* indeterminated */ - -/* Link Speed Parameter */ -#define SK_LSPEED_AUTO 1 /* Automatic resolution */ -#define SK_LSPEED_10MBPS 2 /* 10 Mbps */ -#define SK_LSPEED_100MBPS 3 /* 100 Mbps */ -#define SK_LSPEED_1000MBPS 4 /* 1000 Mbps */ -#define SK_LSPEED_INDETERMINATED 5 /* indeterminated */ - -/* Link Speed Current State */ -#define SK_LSPEED_STAT_UNKNOWN 1 -#define SK_LSPEED_STAT_10MBPS 2 -#define SK_LSPEED_STAT_100MBPS 3 -#define SK_LSPEED_STAT_1000MBPS 4 -#define SK_LSPEED_STAT_INDETERMINATED 5 - - -/* Link Capability Parameter */ -#define SK_LMODE_CAP_HALF (1<<0) /* Half Duplex Mode */ -#define SK_LMODE_CAP_FULL (1<<1) /* Full Duplex Mode */ -#define SK_LMODE_CAP_AUTOHALF (1<<2) /* AutoHalf Duplex Mode */ -#define SK_LMODE_CAP_AUTOFULL (1<<3) /* AutoFull Duplex Mode */ -#define SK_LMODE_CAP_INDETERMINATED (1<<4) /* indeterminated */ - -/* Link Mode Current State */ -#define SK_LMODE_STAT_UNKNOWN 1 /* Unknown Duplex Mode */ -#define SK_LMODE_STAT_HALF 2 /* Half Duplex Mode */ -#define SK_LMODE_STAT_FULL 3 /* Full Duplex Mode */ -#define SK_LMODE_STAT_AUTOHALF 4 /* Half Duplex Mode obtained by Auto-Neg */ -#define SK_LMODE_STAT_AUTOFULL 5 /* Full Duplex Mode obtained by Auto-Neg */ -#define SK_LMODE_STAT_INDETERMINATED 6 /* indeterminated */ - -/* Flow Control Mode Parameter (and capabilities) */ -#define SK_FLOW_MODE_NONE 1 /* No Flow-Control */ -#define SK_FLOW_MODE_LOC_SEND 2 /* Local station sends PAUSE */ -#define SK_FLOW_MODE_SYMMETRIC 3 /* Both stations may send PAUSE */ -#define SK_FLOW_MODE_SYM_OR_REM 4 /* Both stations may send PAUSE or - * just the remote station may send PAUSE - */ -#define SK_FLOW_MODE_INDETERMINATED 5 /* indeterminated */ - -/* Flow Control Status Parameter */ -#define SK_FLOW_STAT_NONE 1 /* No Flow Control */ -#define SK_FLOW_STAT_REM_SEND 2 /* Remote Station sends PAUSE */ -#define SK_FLOW_STAT_LOC_SEND 3 /* Local station sends PAUSE */ -#define SK_FLOW_STAT_SYMMETRIC 4 /* Both station may send PAUSE */ -#define SK_FLOW_STAT_INDETERMINATED 5 /* indeterminated */ - -/* Master/Slave Mode Capabilities */ -#define SK_MS_CAP_AUTO (1<<0) /* Automatic resolution */ -#define SK_MS_CAP_MASTER (1<<1) /* This station is master */ -#define SK_MS_CAP_SLAVE (1<<2) /* This station is slave */ -#define SK_MS_CAP_INDETERMINATED (1<<3) /* indeterminated */ - -/* Set Master/Slave Mode Parameter (and capabilities) */ -#define SK_MS_MODE_AUTO 1 /* Automatic resolution */ -#define SK_MS_MODE_MASTER 2 /* This station is master */ -#define SK_MS_MODE_SLAVE 3 /* This station is slave */ -#define SK_MS_MODE_INDETERMINATED 4 /* indeterminated */ - -/* Master/Slave Status Parameter */ -#define SK_MS_STAT_UNSET 1 /* The M/S status is not set */ -#define SK_MS_STAT_MASTER 2 /* This station is master */ -#define SK_MS_STAT_SLAVE 3 /* This station is slave */ -#define SK_MS_STAT_FAULT 4 /* M/S resolution failed */ -#define SK_MS_STAT_INDETERMINATED 5 /* indeterminated */ - -/* parameter 'Mode' when calling SkXmSetRxCmd() */ -#define SK_STRIP_FCS_ON (1<<0) /* Enable FCS stripping of Rx frames */ -#define SK_STRIP_FCS_OFF (1<<1) /* Disable FCS stripping of Rx frames */ -#define SK_STRIP_PAD_ON (1<<2) /* Enable pad byte stripping of Rx fr */ -#define SK_STRIP_PAD_OFF (1<<3) /* Disable pad byte stripping of Rx fr */ -#define SK_LENERR_OK_ON (1<<4) /* Don't chk fr for in range len error */ -#define SK_LENERR_OK_OFF (1<<5) /* Check frames for in range len error */ -#define SK_BIG_PK_OK_ON (1<<6) /* Don't set Rx Error bit for big frames */ -#define SK_BIG_PK_OK_OFF (1<<7) /* Set Rx Error bit for big frames */ -#define SK_SELF_RX_ON (1<<8) /* Enable Rx of own packets */ -#define SK_SELF_RX_OFF (1<<9) /* Disable Rx of own packets */ - -/* parameter 'Para' when calling SkMacSetRxTxEn() */ -#define SK_MAC_LOOPB_ON (1<<0) /* Enable MAC Loopback Mode */ -#define SK_MAC_LOOPB_OFF (1<<1) /* Disable MAC Loopback Mode */ -#define SK_PHY_LOOPB_ON (1<<2) /* Enable PHY Loopback Mode */ -#define SK_PHY_LOOPB_OFF (1<<3) /* Disable PHY Loopback Mode */ -#define SK_PHY_FULLD_ON (1<<4) /* Enable GMII Full Duplex */ -#define SK_PHY_FULLD_OFF (1<<5) /* Disable GMII Full Duplex */ - -/* States of PState */ -#define SK_PRT_RESET 0 /* the port is reset */ -#define SK_PRT_STOP 1 /* the port is stopped (similar to SW reset) */ -#define SK_PRT_INIT 2 /* the port is initialized */ -#define SK_PRT_RUN 3 /* the port has an active link */ - -/* PHY power down modes */ -#define PHY_PM_OPERATIONAL_MODE 0 /* PHY operational mode */ -#define PHY_PM_DEEP_SLEEP 1 /* coma mode --> minimal power */ -#define PHY_PM_IEEE_POWER_DOWN 2 /* IEEE 22.2.4.1.5 compl. power down */ -#define PHY_PM_ENERGY_DETECT 3 /* energy detect */ -#define PHY_PM_ENERGY_DETECT_PLUS 4 /* energy detect plus */ - -/* Default receive frame limit for Workaround of XMAC Errata */ -#define SK_DEF_RX_WA_LIM SK_CONSTU64(100) - -/* values for GILedBlinkCtrl (LED Blink Control) */ -#define SK_ACT_LED_BLINK (1<<0) /* Active LED blinking */ -#define SK_DUP_LED_NORMAL (1<<1) /* Duplex LED normal */ -#define SK_LED_LINK100_ON (1<<2) /* Link 100M LED on */ - -/* Link Partner Status */ -#define SK_LIPA_UNKNOWN 0 /* Link partner is in unknown state */ -#define SK_LIPA_MANUAL 1 /* Link partner is in detected manual state */ -#define SK_LIPA_AUTO 2 /* Link partner is in auto-negotiation state */ - -/* Maximum Restarts before restart is ignored (3Com WA) */ -#define SK_MAX_LRESTART 3 /* Max. 3 times the link is restarted */ - -/* Max. Auto-neg. timeouts before link detection in sense mode is reset */ -#define SK_MAX_ANEG_TO 10 /* Max. 10 times the sense mode is reset */ - -/* structures *****************************************************************/ - -/* - * MAC specific functions - */ -typedef struct s_GeMacFunc { - int (*pFnMacUpdateStats)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); - int (*pFnMacStatistic)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 StatAddr, SK_U32 SK_FAR *pVal); - int (*pFnMacResetCounter)(SK_AC *pAC, SK_IOC IoC, unsigned int Port); - int (*pFnMacOverflow)(SK_AC *pAC, SK_IOC IoC, unsigned int Port, - SK_U16 IStatus, SK_U64 SK_FAR *pVal); -} SK_GEMACFUNC; - -/* - * Port Structure - */ -typedef struct s_GePort { -#ifndef SK_DIAG - SK_TIMER PWaTimer; /* Workaround Timer */ - SK_TIMER HalfDupChkTimer; -#endif /* SK_DIAG */ - SK_U32 PPrevShorts; /* Previous Short Counter checking */ - SK_U32 PPrevFcs; /* Previous FCS Error Counter checking */ - SK_U64 PPrevRx; /* Previous RxOk Counter checking */ - SK_U64 PRxLim; /* Previous RxOk Counter checking */ - SK_U64 LastOctets; /* For half duplex hang check */ - int PLinkResCt; /* Link Restart Counter */ - int PAutoNegTimeOut;/* Auto-negotiation timeout current value */ - int PAutoNegTOCt; /* Auto-negotiation Timeout Counter */ - int PRxQSize; /* Port Rx Queue Size in kB */ - int PXSQSize; /* Port Synchronous Transmit Queue Size in kB */ - int PXAQSize; /* Port Asynchronous Transmit Queue Size in kB */ - SK_U32 PRxQRamStart; /* Receive Queue RAM Buffer Start Address */ - SK_U32 PRxQRamEnd; /* Receive Queue RAM Buffer End Address */ - SK_U32 PXsQRamStart; /* Sync Tx Queue RAM Buffer Start Address */ - SK_U32 PXsQRamEnd; /* Sync Tx Queue RAM Buffer End Address */ - SK_U32 PXaQRamStart; /* Async Tx Queue RAM Buffer Start Address */ - SK_U32 PXaQRamEnd; /* Async Tx Queue RAM Buffer End Address */ - SK_U32 PRxOverCnt; /* Receive Overflow Counter */ - int PRxQOff; /* Rx Queue Address Offset */ - int PXsQOff; /* Synchronous Tx Queue Address Offset */ - int PXaQOff; /* Asynchronous Tx Queue Address Offset */ - int PhyType; /* PHY used on this port */ - int PState; /* Port status (reset, stop, init, run) */ - SK_U16 PhyId1; /* PHY Id1 on this port */ - SK_U16 PhyAddr; /* MDIO/MDC PHY address */ - SK_U16 PIsave; /* Saved Interrupt status word */ - SK_U16 PSsave; /* Saved PHY status word */ - SK_U16 PGmANegAdv; /* Saved GPhy AutoNegAdvertisment register */ - SK_BOOL PHWLinkUp; /* The hardware Link is up (wiring) */ - SK_BOOL PLinkBroken; /* Is Link broken ? */ - SK_BOOL PCheckPar; /* Do we check for parity errors ? */ - SK_BOOL HalfDupTimerActive; - SK_U8 PLinkCap; /* Link Capabilities */ - SK_U8 PLinkModeConf; /* Link Mode configured */ - SK_U8 PLinkMode; /* Link Mode currently used */ - SK_U8 PLinkModeStatus;/* Link Mode Status */ - SK_U8 PLinkSpeedCap; /* Link Speed Capabilities(10/100/1000 Mbps) */ - SK_U8 PLinkSpeed; /* configured Link Speed (10/100/1000 Mbps) */ - SK_U8 PLinkSpeedUsed; /* current Link Speed (10/100/1000 Mbps) */ - SK_U8 PFlowCtrlCap; /* Flow Control Capabilities */ - SK_U8 PFlowCtrlMode; /* Flow Control Mode */ - SK_U8 PFlowCtrlStatus;/* Flow Control Status */ - SK_U8 PMSCap; /* Master/Slave Capabilities */ - SK_U8 PMSMode; /* Master/Slave Mode */ - SK_U8 PMSStatus; /* Master/Slave Status */ - SK_BOOL PAutoNegFail; /* Auto-negotiation fail flag */ - SK_U8 PLipaAutoNeg; /* Auto-negotiation possible with Link Partner */ - SK_U8 PCableLen; /* Cable Length */ - SK_U8 PMdiPairLen[4]; /* MDI[0..3] Pair Length */ - SK_U8 PMdiPairSts[4]; /* MDI[0..3] Pair Diagnostic Status */ - SK_U8 PPhyPowerState; /* PHY current power state */ - int PMacColThres; /* MAC Collision Threshold */ - int PMacJamLen; /* MAC Jam length */ - int PMacJamIpgVal; /* MAC Jam IPG */ - int PMacJamIpgData; /* MAC IPG Jam to Data */ - int PMacIpgData; /* MAC Data IPG */ - SK_BOOL PMacLimit4; /* reset collision counter and backoff algorithm */ -} SK_GEPORT; - -/* - * Gigabit Ethernet Initialization Struct - * (has to be included in the adapter context) - */ -typedef struct s_GeInit { - int GIChipId; /* Chip Identification Number */ - int GIChipRev; /* Chip Revision Number */ - SK_U8 GIPciHwRev; /* PCI HW Revision Number */ - SK_BOOL GIGenesis; /* Genesis adapter ? */ - SK_BOOL GIYukon; /* YUKON-A1/Bx chip */ - SK_BOOL GIYukonLite; /* YUKON-Lite chip */ - SK_BOOL GICopperType; /* Copper Type adapter ? */ - SK_BOOL GIPciSlot64; /* 64-bit PCI Slot */ - SK_BOOL GIPciClock66; /* 66 MHz PCI Clock */ - SK_BOOL GIVauxAvail; /* VAUX available (YUKON) */ - SK_BOOL GIYukon32Bit; /* 32-Bit YUKON adapter */ - SK_U16 GILedBlinkCtrl; /* LED Blink Control */ - int GIMacsFound; /* Number of MACs found on this adapter */ - int GIMacType; /* MAC Type used on this adapter */ - int GIHstClkFact; /* Host Clock Factor (62.5 / HstClk * 100) */ - int GIPortUsage; /* Driver Port Usage */ - int GILevel; /* Initialization Level completed */ - int GIRamSize; /* The RAM size of the adapter in kB */ - int GIWolOffs; /* WOL Register Offset (HW-Bug in Rev. A) */ - SK_U32 GIRamOffs; /* RAM Address Offset for addr calculation */ - SK_U32 GIPollTimerVal; /* Descr. Poll Timer Init Val (HstClk ticks) */ - SK_U32 GIValIrqMask; /* Value for Interrupt Mask */ - SK_U32 GITimeStampCnt; /* Time Stamp High Counter (YUKON only) */ - SK_GEPORT GP[SK_MAX_MACS];/* Port Dependent Information */ - SK_GEMACFUNC GIFunc; /* MAC depedent functions */ -} SK_GEINIT; - -/* - * Error numbers and messages for skxmac2.c and skgeinit.c - */ -#define SKERR_HWI_E001 (SK_ERRBASE_HWINIT) -#define SKERR_HWI_E001MSG "SkXmClrExactAddr() has got illegal parameters" -#define SKERR_HWI_E002 (SKERR_HWI_E001+1) -#define SKERR_HWI_E002MSG "SkGeInit(): Level 1 call missing" -#define SKERR_HWI_E003 (SKERR_HWI_E002+1) -#define SKERR_HWI_E003MSG "SkGeInit() called with illegal init Level" -#define SKERR_HWI_E004 (SKERR_HWI_E003+1) -#define SKERR_HWI_E004MSG "SkGeInitPort(): Queue Size illegal configured" -#define SKERR_HWI_E005 (SKERR_HWI_E004+1) -#define SKERR_HWI_E005MSG "SkGeInitPort(): cannot init running ports" -#define SKERR_HWI_E006 (SKERR_HWI_E005+1) -#define SKERR_HWI_E006MSG "SkGeMacInit(): PState does not match HW state" -#define SKERR_HWI_E007 (SKERR_HWI_E006+1) -#define SKERR_HWI_E007MSG "SkXmInitDupMd() called with invalid Dup Mode" -#define SKERR_HWI_E008 (SKERR_HWI_E007+1) -#define SKERR_HWI_E008MSG "SkXmSetRxCmd() called with invalid Mode" -#define SKERR_HWI_E009 (SKERR_HWI_E008+1) -#define SKERR_HWI_E009MSG "SkGeCfgSync() called although PXSQSize zero" -#define SKERR_HWI_E010 (SKERR_HWI_E009+1) -#define SKERR_HWI_E010MSG "SkGeCfgSync() called with invalid parameters" -#define SKERR_HWI_E011 (SKERR_HWI_E010+1) -#define SKERR_HWI_E011MSG "SkGeInitPort(): Receive Queue Size too small" -#define SKERR_HWI_E012 (SKERR_HWI_E011+1) -#define SKERR_HWI_E012MSG "SkGeInitPort(): invalid Queue Size specified" -#define SKERR_HWI_E013 (SKERR_HWI_E012+1) -#define SKERR_HWI_E013MSG "SkGeInitPort(): cfg changed for running queue" -#define SKERR_HWI_E014 (SKERR_HWI_E013+1) -#define SKERR_HWI_E014MSG "SkGeInitPort(): unknown GIPortUsage specified" -#define SKERR_HWI_E015 (SKERR_HWI_E014+1) -#define SKERR_HWI_E015MSG "Illegal Link mode parameter" -#define SKERR_HWI_E016 (SKERR_HWI_E015+1) -#define SKERR_HWI_E016MSG "Illegal Flow control mode parameter" -#define SKERR_HWI_E017 (SKERR_HWI_E016+1) -#define SKERR_HWI_E017MSG "Illegal value specified for GIPollTimerVal" -#define SKERR_HWI_E018 (SKERR_HWI_E017+1) -#define SKERR_HWI_E018MSG "FATAL: SkGeStopPort() does not terminate (Tx)" -#define SKERR_HWI_E019 (SKERR_HWI_E018+1) -#define SKERR_HWI_E019MSG "Illegal Speed parameter" -#define SKERR_HWI_E020 (SKERR_HWI_E019+1) -#define SKERR_HWI_E020MSG "Illegal Master/Slave parameter" -#define SKERR_HWI_E021 (SKERR_HWI_E020+1) -#define SKERR_HWI_E021MSG "MacUpdateStats(): cannot update statistic counter" -#define SKERR_HWI_E022 (SKERR_HWI_E021+1) -#define SKERR_HWI_E022MSG "MacStatistic(): illegal statistic base address" -#define SKERR_HWI_E023 (SKERR_HWI_E022+1) -#define SKERR_HWI_E023MSG "SkGeInitPort(): Transmit Queue Size too small" -#define SKERR_HWI_E024 (SKERR_HWI_E023+1) -#define SKERR_HWI_E024MSG "FATAL: SkGeStopPort() does not terminate (Rx)" -#define SKERR_HWI_E025 (SKERR_HWI_E024+1) -#define SKERR_HWI_E025MSG "" - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO - -/* - * public functions in skgeinit.c - */ -extern void SkGePollTxD( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL PollTxD); - -extern void SkGeYellowLED( - SK_AC *pAC, - SK_IOC IoC, - int State); - -extern int SkGeCfgSync( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U32 IntTime, - SK_U32 LimCount, - int SyncMode); - -extern void SkGeLoadLnkSyncCnt( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U32 CntVal); - -extern void SkGeStopPort( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Dir, - int RstMode); - -extern int SkGeInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern void SkGeDeInit( - SK_AC *pAC, - SK_IOC IoC); - -extern int SkGeInitPort( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkGeXmitLED( - SK_AC *pAC, - SK_IOC IoC, - int Led, - int Mode); - -extern int SkGeInitAssignRamToQueues( - SK_AC *pAC, - int ActivePort, - SK_BOOL DualNet); - -/* - * public functions in skxmac2.c - */ -extern void SkMacRxTxDisable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacSoftRst( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacHardRst( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkXmInitMac( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkGmInitMac( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacInitPhy( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL DoLoop); - -extern void SkMacIrqDisable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacFlushTxFifo( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacIrq( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern int SkMacAutoNegDone( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacAutoNegLipaPhy( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U16 IStatus); - -extern int SkMacRxTxEnable( - SK_AC *pAC, - SK_IOC IoC, - int Port); - -extern void SkMacPromiscMode( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); - -extern void SkMacHashing( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); - -extern void SkXmPhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 SK_FAR *pVal); - -extern void SkXmPhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkGmPhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 SK_FAR *pVal); - -extern void SkGmPhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkXmClrExactAddr( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int StartNum, - int StopNum); - -extern void SkXmAutoNegLipaXmac( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_U16 IStatus); - -extern int SkXmUpdateStats( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkGmUpdateStats( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkXmMacStatistic( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 StatAddr, - SK_U32 SK_FAR *pVal); - -extern int SkGmMacStatistic( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 StatAddr, - SK_U32 SK_FAR *pVal); - -extern int SkXmResetCounter( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkGmResetCounter( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port); - -extern int SkXmOverflowStatus( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 IStatus, - SK_U64 SK_FAR *pStatus); - -extern int SkGmOverflowStatus( - SK_AC *pAC, - SK_IOC IoC, - unsigned int Port, - SK_U16 MacStatus, - SK_U64 SK_FAR *pStatus); - -extern int SkGmCableDiagStatus( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL StartTest); - -#ifdef SK_DIAG -extern void SkGePhyRead( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 *pVal); - -extern void SkGePhyWrite( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Addr, - SK_U16 Val); - -extern void SkMacSetRxCmd( - SK_AC *pAC, - SK_IOC IoC, - int Port, - int Mode); -extern void SkMacCrcGener( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -extern void SkMacTimeStamp( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -extern void SkXmSendCont( - SK_AC *pAC, - SK_IOC IoC, - int Port, - SK_BOOL Enable); -#endif /* SK_DIAG */ - -#else /* SK_KR_PROTO */ - -/* - * public functions in skgeinit.c - */ -extern void SkGePollTxD(); -extern void SkGeYellowLED(); -extern int SkGeCfgSync(); -extern void SkGeLoadLnkSyncCnt(); -extern void SkGeStopPort(); -extern int SkGeInit(); -extern void SkGeDeInit(); -extern int SkGeInitPort(); -extern void SkGeXmitLED(); -extern int SkGeInitAssignRamToQueues(); - -/* - * public functions in skxmac2.c - */ -extern void SkMacRxTxDisable(); -extern void SkMacSoftRst(); -extern void SkMacHardRst(); -extern void SkMacInitPhy(); -extern int SkMacRxTxEnable(); -extern void SkMacPromiscMode(); -extern void SkMacHashing(); -extern void SkMacIrqDisable(); -extern void SkMacFlushTxFifo(); -extern void SkMacIrq(); -extern int SkMacAutoNegDone(); -extern void SkMacAutoNegLipaPhy(); -extern void SkXmInitMac(); -extern void SkXmPhyRead(); -extern void SkXmPhyWrite(); -extern void SkGmInitMac(); -extern void SkGmPhyRead(); -extern void SkGmPhyWrite(); -extern void SkXmClrExactAddr(); -extern void SkXmAutoNegLipaXmac(); -extern int SkXmUpdateStats(); -extern int SkGmUpdateStats(); -extern int SkXmMacStatistic(); -extern int SkGmMacStatistic(); -extern int SkXmResetCounter(); -extern int SkGmResetCounter(); -extern int SkXmOverflowStatus(); -extern int SkGmOverflowStatus(); -extern int SkGmCableDiagStatus(); - -#ifdef SK_DIAG -extern void SkGePhyRead(); -extern void SkGePhyWrite(); -extern void SkMacSetRxCmd(); -extern void SkMacCrcGener(); -extern void SkMacTimeStamp(); -extern void SkXmSendCont(); -#endif /* SK_DIAG */ - -#endif /* SK_KR_PROTO */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKGEINIT_H_ */ diff --git a/drivers/net/sk98lin/h/skgepnm2.h b/drivers/net/sk98lin/h/skgepnm2.h deleted file mode 100644 index ddd304f1a48b..000000000000 --- a/drivers/net/sk98lin/h/skgepnm2.h +++ /dev/null @@ -1,334 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnm2.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.36 $ - * Date: $Date: 2003/05/23 12:45:13 $ - * Purpose: Defines for Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef _SKGEPNM2_H_ -#define _SKGEPNM2_H_ - -/* - * General definitions - */ -#define SK_PNMI_CHIPSET_XMAC 1 /* XMAC11800FP */ -#define SK_PNMI_CHIPSET_YUKON 2 /* YUKON */ - -#define SK_PNMI_BUS_PCI 1 /* PCI bus*/ - -/* - * Actions - */ -#define SK_PNMI_ACT_IDLE 1 -#define SK_PNMI_ACT_RESET 2 -#define SK_PNMI_ACT_SELFTEST 3 -#define SK_PNMI_ACT_RESETCNT 4 - -/* - * VPD releated defines - */ - -#define SK_PNMI_VPD_RW 1 -#define SK_PNMI_VPD_RO 2 - -#define SK_PNMI_VPD_OK 0 -#define SK_PNMI_VPD_NOTFOUND 1 -#define SK_PNMI_VPD_CUT 2 -#define SK_PNMI_VPD_TIMEOUT 3 -#define SK_PNMI_VPD_FULL 4 -#define SK_PNMI_VPD_NOWRITE 5 -#define SK_PNMI_VPD_FATAL 6 - -#define SK_PNMI_VPD_IGNORE 0 -#define SK_PNMI_VPD_CREATE 1 -#define SK_PNMI_VPD_DELETE 2 - - -/* - * RLMT related defines - */ -#define SK_PNMI_DEF_RLMT_CHG_THRES 240 /* 4 changes per minute */ - - -/* - * VCT internal status values - */ -#define SK_PNMI_VCT_PENDING 32 -#define SK_PNMI_VCT_TEST_DONE 64 -#define SK_PNMI_VCT_LINK 128 - -/* - * Internal table definitions - */ -#define SK_PNMI_GET 0 -#define SK_PNMI_PRESET 1 -#define SK_PNMI_SET 2 - -#define SK_PNMI_RO 0 -#define SK_PNMI_RW 1 -#define SK_PNMI_WO 2 - -typedef struct s_OidTabEntry { - SK_U32 Id; - SK_U32 InstanceNo; - unsigned int StructSize; - unsigned int Offset; - int Access; - int (* Func)(SK_AC *pAc, SK_IOC pIo, int action, - SK_U32 Id, char* pBuf, unsigned int* pLen, - SK_U32 Instance, unsigned int TableIndex, - SK_U32 NetNumber); - SK_U16 Param; -} SK_PNMI_TAB_ENTRY; - - -/* - * Trap lengths - */ -#define SK_PNMI_TRAP_SIMPLE_LEN 17 -#define SK_PNMI_TRAP_SENSOR_LEN_BASE 46 -#define SK_PNMI_TRAP_RLMT_CHANGE_LEN 23 -#define SK_PNMI_TRAP_RLMT_PORT_LEN 23 - -/* - * Number of MAC types supported - */ -#define SK_PNMI_MAC_TYPES (SK_MAC_GMAC + 1) - -/* - * MAC statistic data list (overall set for MAC types used) - */ -enum SK_MACSTATS { - SK_PNMI_HTX = 0, - SK_PNMI_HTX_OCTET, - SK_PNMI_HTX_OCTETHIGH = SK_PNMI_HTX_OCTET, - SK_PNMI_HTX_OCTETLOW, - SK_PNMI_HTX_BROADCAST, - SK_PNMI_HTX_MULTICAST, - SK_PNMI_HTX_UNICAST, - SK_PNMI_HTX_BURST, - SK_PNMI_HTX_PMACC, - SK_PNMI_HTX_MACC, - SK_PNMI_HTX_COL, - SK_PNMI_HTX_SINGLE_COL, - SK_PNMI_HTX_MULTI_COL, - SK_PNMI_HTX_EXCESS_COL, - SK_PNMI_HTX_LATE_COL, - SK_PNMI_HTX_DEFFERAL, - SK_PNMI_HTX_EXCESS_DEF, - SK_PNMI_HTX_UNDERRUN, - SK_PNMI_HTX_CARRIER, - SK_PNMI_HTX_UTILUNDER, - SK_PNMI_HTX_UTILOVER, - SK_PNMI_HTX_64, - SK_PNMI_HTX_127, - SK_PNMI_HTX_255, - SK_PNMI_HTX_511, - SK_PNMI_HTX_1023, - SK_PNMI_HTX_MAX, - SK_PNMI_HTX_LONGFRAMES, - SK_PNMI_HTX_SYNC, - SK_PNMI_HTX_SYNC_OCTET, - SK_PNMI_HTX_RESERVED, - - SK_PNMI_HRX, - SK_PNMI_HRX_OCTET, - SK_PNMI_HRX_OCTETHIGH = SK_PNMI_HRX_OCTET, - SK_PNMI_HRX_OCTETLOW, - SK_PNMI_HRX_BADOCTET, - SK_PNMI_HRX_BADOCTETHIGH = SK_PNMI_HRX_BADOCTET, - SK_PNMI_HRX_BADOCTETLOW, - SK_PNMI_HRX_BROADCAST, - SK_PNMI_HRX_MULTICAST, - SK_PNMI_HRX_UNICAST, - SK_PNMI_HRX_PMACC, - SK_PNMI_HRX_MACC, - SK_PNMI_HRX_PMACC_ERR, - SK_PNMI_HRX_MACC_UNKWN, - SK_PNMI_HRX_BURST, - SK_PNMI_HRX_MISSED, - SK_PNMI_HRX_FRAMING, - SK_PNMI_HRX_UNDERSIZE, - SK_PNMI_HRX_OVERFLOW, - SK_PNMI_HRX_JABBER, - SK_PNMI_HRX_CARRIER, - SK_PNMI_HRX_IRLENGTH, - SK_PNMI_HRX_SYMBOL, - SK_PNMI_HRX_SHORTS, - SK_PNMI_HRX_RUNT, - SK_PNMI_HRX_TOO_LONG, - SK_PNMI_HRX_FCS, - SK_PNMI_HRX_CEXT, - SK_PNMI_HRX_UTILUNDER, - SK_PNMI_HRX_UTILOVER, - SK_PNMI_HRX_64, - SK_PNMI_HRX_127, - SK_PNMI_HRX_255, - SK_PNMI_HRX_511, - SK_PNMI_HRX_1023, - SK_PNMI_HRX_MAX, - SK_PNMI_HRX_LONGFRAMES, - - SK_PNMI_HRX_RESERVED, - - SK_PNMI_MAX_IDX /* NOTE: Ensure SK_PNMI_CNT_NO is set to this value */ -}; - -/* - * MAC specific data - */ -typedef struct s_PnmiStatAddr { - SK_U16 Reg; /* MAC register containing the value */ - SK_BOOL GetOffset; /* TRUE: Offset managed by PNMI (call GetStatVal())*/ -} SK_PNMI_STATADDR; - - -/* - * SK_PNMI_STRUCT_DATA copy offset evaluation macros - */ -#define SK_PNMI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e)) -#define SK_PNMI_MAI_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STRUCT_DATA *)0)->e)) -#define SK_PNMI_VPD_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_VPD *)0)->e)) -#define SK_PNMI_SEN_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_SENSOR *)0)->e)) -#define SK_PNMI_CHK_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CHECKSUM *)0)->e)) -#define SK_PNMI_STA_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_STAT *)0)->e)) -#define SK_PNMI_CNF_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_CONF *)0)->e)) -#define SK_PNMI_RLM_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT *)0)->e)) -#define SK_PNMI_MON_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_RLMT_MONITOR *)0)->e)) -#define SK_PNMI_TRP_OFF(e) ((SK_U32)(SK_UPTR)&(((SK_PNMI_TRAP *)0)->e)) - -#define SK_PNMI_SET_STAT(b,s,o) {SK_U32 Val32; char *pVal; \ - Val32 = (s); \ - pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \ - &(((SK_PNMI_STRUCT_DATA *)0)-> \ - ReturnStatus.ErrorStatus)); \ - SK_PNMI_STORE_U32(pVal, Val32); \ - Val32 = (o); \ - pVal = (char *)(b) + ((SK_U32)(SK_UPTR) \ - &(((SK_PNMI_STRUCT_DATA *)0)-> \ - ReturnStatus.ErrorOffset)); \ - SK_PNMI_STORE_U32(pVal, Val32);} - -/* - * Time macros - */ -#ifndef SK_PNMI_HUNDREDS_SEC -#if SK_TICKS_PER_SEC == 100 -#define SK_PNMI_HUNDREDS_SEC(t) (t) -#else -#define SK_PNMI_HUNDREDS_SEC(t) (((t) * 100) / (SK_TICKS_PER_SEC)) -#endif /* !SK_TICKS_PER_SEC */ -#endif /* !SK_PNMI_HUNDREDS_SEC */ - -/* - * Macros to work around alignment problems - */ -#ifndef SK_PNMI_STORE_U16 -#define SK_PNMI_STORE_U16(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1);} -#endif - -#ifndef SK_PNMI_STORE_U32 -#define SK_PNMI_STORE_U32(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1); \ - *((char *)(p) + 2) = \ - *(((char *)&(v)) + 2); \ - *((char *)(p) + 3) = \ - *(((char *)&(v)) + 3);} -#endif - -#ifndef SK_PNMI_STORE_U64 -#define SK_PNMI_STORE_U64(p,v) {*(char *)(p) = *((char *)&(v)); \ - *((char *)(p) + 1) = \ - *(((char *)&(v)) + 1); \ - *((char *)(p) + 2) = \ - *(((char *)&(v)) + 2); \ - *((char *)(p) + 3) = \ - *(((char *)&(v)) + 3); \ - *((char *)(p) + 4) = \ - *(((char *)&(v)) + 4); \ - *((char *)(p) + 5) = \ - *(((char *)&(v)) + 5); \ - *((char *)(p) + 6) = \ - *(((char *)&(v)) + 6); \ - *((char *)(p) + 7) = \ - *(((char *)&(v)) + 7);} -#endif - -#ifndef SK_PNMI_READ_U16 -#define SK_PNMI_READ_U16(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1);} -#endif - -#ifndef SK_PNMI_READ_U32 -#define SK_PNMI_READ_U32(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1); \ - *(((char *)&(v)) + 2) = \ - *((char *)(p) + 2); \ - *(((char *)&(v)) + 3) = \ - *((char *)(p) + 3);} -#endif - -#ifndef SK_PNMI_READ_U64 -#define SK_PNMI_READ_U64(p,v) {*((char *)&(v)) = *(char *)(p); \ - *(((char *)&(v)) + 1) = \ - *((char *)(p) + 1); \ - *(((char *)&(v)) + 2) = \ - *((char *)(p) + 2); \ - *(((char *)&(v)) + 3) = \ - *((char *)(p) + 3); \ - *(((char *)&(v)) + 4) = \ - *((char *)(p) + 4); \ - *(((char *)&(v)) + 5) = \ - *((char *)(p) + 5); \ - *(((char *)&(v)) + 6) = \ - *((char *)(p) + 6); \ - *(((char *)&(v)) + 7) = \ - *((char *)(p) + 7);} -#endif - -/* - * Macros for Debug - */ -#ifdef DEBUG - -#define SK_PNMI_CHECKFLAGS(vSt) {if (pAC->Pnmi.MacUpdatedFlag > 0 || \ - pAC->Pnmi.RlmtUpdatedFlag > 0 || \ - pAC->Pnmi.SirqUpdatedFlag > 0) { \ - SK_DBG_MSG(pAC, \ - SK_DBGMOD_PNMI, \ - SK_DBGCAT_CTRL, \ - ("PNMI: ERR: %s MacUFlag=%d, RlmtUFlag=%d, SirqUFlag=%d\n", \ - vSt, \ - pAC->Pnmi.MacUpdatedFlag, \ - pAC->Pnmi.RlmtUpdatedFlag, \ - pAC->Pnmi.SirqUpdatedFlag))}} - -#else /* !DEBUG */ - -#define SK_PNMI_CHECKFLAGS(vSt) /* Nothing */ - -#endif /* !DEBUG */ - -#endif /* _SKGEPNM2_H_ */ diff --git a/drivers/net/sk98lin/h/skgepnmi.h b/drivers/net/sk98lin/h/skgepnmi.h deleted file mode 100644 index 1ed214ccb253..000000000000 --- a/drivers/net/sk98lin/h/skgepnmi.h +++ /dev/null @@ -1,962 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnmi.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.62 $ - * Date: $Date: 2003/08/15 12:31:52 $ - * Purpose: Defines for Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef _SKGEPNMI_H_ -#define _SKGEPNMI_H_ - -/* - * Include dependencies - */ -#include "h/sktypes.h" -#include "h/skerror.h" -#include "h/sktimer.h" -#include "h/ski2c.h" -#include "h/skaddr.h" -#include "h/skrlmt.h" -#include "h/skvpd.h" - -/* - * Management Database Version - */ -#define SK_PNMI_MDB_VERSION 0x00030001 /* 3.1 */ - - -/* - * Event definitions - */ -#define SK_PNMI_EVT_SIRQ_OVERFLOW 1 /* Counter overflow */ -#define SK_PNMI_EVT_SEN_WAR_LOW 2 /* Lower war thres exceeded */ -#define SK_PNMI_EVT_SEN_WAR_UPP 3 /* Upper war thres exceeded */ -#define SK_PNMI_EVT_SEN_ERR_LOW 4 /* Lower err thres exceeded */ -#define SK_PNMI_EVT_SEN_ERR_UPP 5 /* Upper err thres exceeded */ -#define SK_PNMI_EVT_CHG_EST_TIMER 6 /* Timer event for RLMT Chg */ -#define SK_PNMI_EVT_UTILIZATION_TIMER 7 /* Timer event for Utiliza. */ -#define SK_PNMI_EVT_CLEAR_COUNTER 8 /* Clear statistic counters */ -#define SK_PNMI_EVT_XMAC_RESET 9 /* XMAC will be reset */ - -#define SK_PNMI_EVT_RLMT_PORT_UP 10 /* Port came logically up */ -#define SK_PNMI_EVT_RLMT_PORT_DOWN 11 /* Port went logically down */ -#define SK_PNMI_EVT_RLMT_SEGMENTATION 13 /* Two SP root bridges found */ -#define SK_PNMI_EVT_RLMT_ACTIVE_DOWN 14 /* Port went logically down */ -#define SK_PNMI_EVT_RLMT_ACTIVE_UP 15 /* Port came logically up */ -#define SK_PNMI_EVT_RLMT_SET_NETS 16 /* 1. Parameter is number of nets - 1 = single net; 2 = dual net */ -#define SK_PNMI_EVT_VCT_RESET 17 /* VCT port reset timer event started with SET. */ - - -/* - * Return values - */ -#define SK_PNMI_ERR_OK 0 -#define SK_PNMI_ERR_GENERAL 1 -#define SK_PNMI_ERR_TOO_SHORT 2 -#define SK_PNMI_ERR_BAD_VALUE 3 -#define SK_PNMI_ERR_READ_ONLY 4 -#define SK_PNMI_ERR_UNKNOWN_OID 5 -#define SK_PNMI_ERR_UNKNOWN_INST 6 -#define SK_PNMI_ERR_UNKNOWN_NET 7 -#define SK_PNMI_ERR_NOT_SUPPORTED 10 - - -/* - * Return values of driver reset function SK_DRIVER_RESET() and - * driver event function SK_DRIVER_EVENT() - */ -#define SK_PNMI_ERR_OK 0 -#define SK_PNMI_ERR_FAIL 1 - - -/* - * Return values of driver test function SK_DRIVER_SELFTEST() - */ -#define SK_PNMI_TST_UNKNOWN (1 << 0) -#define SK_PNMI_TST_TRANCEIVER (1 << 1) -#define SK_PNMI_TST_ASIC (1 << 2) -#define SK_PNMI_TST_SENSOR (1 << 3) -#define SK_PNMI_TST_POWERMGMT (1 << 4) -#define SK_PNMI_TST_PCI (1 << 5) -#define SK_PNMI_TST_MAC (1 << 6) - - -/* - * RLMT specific definitions - */ -#define SK_PNMI_RLMT_STATUS_STANDBY 1 -#define SK_PNMI_RLMT_STATUS_ACTIVE 2 -#define SK_PNMI_RLMT_STATUS_ERROR 3 - -#define SK_PNMI_RLMT_LSTAT_PHY_DOWN 1 -#define SK_PNMI_RLMT_LSTAT_AUTONEG 2 -#define SK_PNMI_RLMT_LSTAT_LOG_DOWN 3 -#define SK_PNMI_RLMT_LSTAT_LOG_UP 4 -#define SK_PNMI_RLMT_LSTAT_INDETERMINATED 5 - -#define SK_PNMI_RLMT_MODE_CHK_LINK (SK_RLMT_CHECK_LINK) -#define SK_PNMI_RLMT_MODE_CHK_RX (SK_RLMT_CHECK_LOC_LINK) -#define SK_PNMI_RLMT_MODE_CHK_SPT (SK_RLMT_CHECK_SEG) -/* #define SK_PNMI_RLMT_MODE_CHK_EX */ - -/* - * OID definition - */ -#ifndef _NDIS_ /* Check, whether NDIS already included OIDs */ - -#define OID_GEN_XMIT_OK 0x00020101 -#define OID_GEN_RCV_OK 0x00020102 -#define OID_GEN_XMIT_ERROR 0x00020103 -#define OID_GEN_RCV_ERROR 0x00020104 -#define OID_GEN_RCV_NO_BUFFER 0x00020105 - -/* #define OID_GEN_DIRECTED_BYTES_XMIT 0x00020201 */ -#define OID_GEN_DIRECTED_FRAMES_XMIT 0x00020202 -/* #define OID_GEN_MULTICAST_BYTES_XMIT 0x00020203 */ -#define OID_GEN_MULTICAST_FRAMES_XMIT 0x00020204 -/* #define OID_GEN_BROADCAST_BYTES_XMIT 0x00020205 */ -#define OID_GEN_BROADCAST_FRAMES_XMIT 0x00020206 -/* #define OID_GEN_DIRECTED_BYTES_RCV 0x00020207 */ -#define OID_GEN_DIRECTED_FRAMES_RCV 0x00020208 -/* #define OID_GEN_MULTICAST_BYTES_RCV 0x00020209 */ -#define OID_GEN_MULTICAST_FRAMES_RCV 0x0002020A -/* #define OID_GEN_BROADCAST_BYTES_RCV 0x0002020B */ -#define OID_GEN_BROADCAST_FRAMES_RCV 0x0002020C -#define OID_GEN_RCV_CRC_ERROR 0x0002020D -#define OID_GEN_TRANSMIT_QUEUE_LENGTH 0x0002020E - -#define OID_802_3_PERMANENT_ADDRESS 0x01010101 -#define OID_802_3_CURRENT_ADDRESS 0x01010102 -/* #define OID_802_3_MULTICAST_LIST 0x01010103 */ -/* #define OID_802_3_MAXIMUM_LIST_SIZE 0x01010104 */ -/* #define OID_802_3_MAC_OPTIONS 0x01010105 */ - -#define OID_802_3_RCV_ERROR_ALIGNMENT 0x01020101 -#define OID_802_3_XMIT_ONE_COLLISION 0x01020102 -#define OID_802_3_XMIT_MORE_COLLISIONS 0x01020103 -#define OID_802_3_XMIT_DEFERRED 0x01020201 -#define OID_802_3_XMIT_MAX_COLLISIONS 0x01020202 -#define OID_802_3_RCV_OVERRUN 0x01020203 -#define OID_802_3_XMIT_UNDERRUN 0x01020204 -#define OID_802_3_XMIT_TIMES_CRS_LOST 0x01020206 -#define OID_802_3_XMIT_LATE_COLLISIONS 0x01020207 - -/* - * PnP and PM OIDs - */ -#ifdef SK_POWER_MGMT -#define OID_PNP_CAPABILITIES 0xFD010100 -#define OID_PNP_SET_POWER 0xFD010101 -#define OID_PNP_QUERY_POWER 0xFD010102 -#define OID_PNP_ADD_WAKE_UP_PATTERN 0xFD010103 -#define OID_PNP_REMOVE_WAKE_UP_PATTERN 0xFD010104 -#define OID_PNP_ENABLE_WAKE_UP 0xFD010106 -#endif /* SK_POWER_MGMT */ - -#endif /* _NDIS_ */ - -#define OID_SKGE_MDB_VERSION 0xFF010100 -#define OID_SKGE_SUPPORTED_LIST 0xFF010101 -#define OID_SKGE_VPD_FREE_BYTES 0xFF010102 -#define OID_SKGE_VPD_ENTRIES_LIST 0xFF010103 -#define OID_SKGE_VPD_ENTRIES_NUMBER 0xFF010104 -#define OID_SKGE_VPD_KEY 0xFF010105 -#define OID_SKGE_VPD_VALUE 0xFF010106 -#define OID_SKGE_VPD_ACCESS 0xFF010107 -#define OID_SKGE_VPD_ACTION 0xFF010108 - -#define OID_SKGE_PORT_NUMBER 0xFF010110 -#define OID_SKGE_DEVICE_TYPE 0xFF010111 -#define OID_SKGE_DRIVER_DESCR 0xFF010112 -#define OID_SKGE_DRIVER_VERSION 0xFF010113 -#define OID_SKGE_HW_DESCR 0xFF010114 -#define OID_SKGE_HW_VERSION 0xFF010115 -#define OID_SKGE_CHIPSET 0xFF010116 -#define OID_SKGE_ACTION 0xFF010117 -#define OID_SKGE_RESULT 0xFF010118 -#define OID_SKGE_BUS_TYPE 0xFF010119 -#define OID_SKGE_BUS_SPEED 0xFF01011A -#define OID_SKGE_BUS_WIDTH 0xFF01011B -/* 0xFF01011C unused */ -#define OID_SKGE_DIAG_ACTION 0xFF01011D -#define OID_SKGE_DIAG_RESULT 0xFF01011E -#define OID_SKGE_MTU 0xFF01011F -#define OID_SKGE_PHYS_CUR_ADDR 0xFF010120 -#define OID_SKGE_PHYS_FAC_ADDR 0xFF010121 -#define OID_SKGE_PMD 0xFF010122 -#define OID_SKGE_CONNECTOR 0xFF010123 -#define OID_SKGE_LINK_CAP 0xFF010124 -#define OID_SKGE_LINK_MODE 0xFF010125 -#define OID_SKGE_LINK_MODE_STATUS 0xFF010126 -#define OID_SKGE_LINK_STATUS 0xFF010127 -#define OID_SKGE_FLOWCTRL_CAP 0xFF010128 -#define OID_SKGE_FLOWCTRL_MODE 0xFF010129 -#define OID_SKGE_FLOWCTRL_STATUS 0xFF01012A -#define OID_SKGE_PHY_OPERATION_CAP 0xFF01012B -#define OID_SKGE_PHY_OPERATION_MODE 0xFF01012C -#define OID_SKGE_PHY_OPERATION_STATUS 0xFF01012D -#define OID_SKGE_MULTICAST_LIST 0xFF01012E -#define OID_SKGE_CURRENT_PACKET_FILTER 0xFF01012F - -#define OID_SKGE_TRAP 0xFF010130 -#define OID_SKGE_TRAP_NUMBER 0xFF010131 - -#define OID_SKGE_RLMT_MODE 0xFF010140 -#define OID_SKGE_RLMT_PORT_NUMBER 0xFF010141 -#define OID_SKGE_RLMT_PORT_ACTIVE 0xFF010142 -#define OID_SKGE_RLMT_PORT_PREFERRED 0xFF010143 -#define OID_SKGE_INTERMEDIATE_SUPPORT 0xFF010160 - -#define OID_SKGE_SPEED_CAP 0xFF010170 -#define OID_SKGE_SPEED_MODE 0xFF010171 -#define OID_SKGE_SPEED_STATUS 0xFF010172 - -#define OID_SKGE_BOARDLEVEL 0xFF010180 - -#define OID_SKGE_SENSOR_NUMBER 0xFF020100 -#define OID_SKGE_SENSOR_INDEX 0xFF020101 -#define OID_SKGE_SENSOR_DESCR 0xFF020102 -#define OID_SKGE_SENSOR_TYPE 0xFF020103 -#define OID_SKGE_SENSOR_VALUE 0xFF020104 -#define OID_SKGE_SENSOR_WAR_THRES_LOW 0xFF020105 -#define OID_SKGE_SENSOR_WAR_THRES_UPP 0xFF020106 -#define OID_SKGE_SENSOR_ERR_THRES_LOW 0xFF020107 -#define OID_SKGE_SENSOR_ERR_THRES_UPP 0xFF020108 -#define OID_SKGE_SENSOR_STATUS 0xFF020109 -#define OID_SKGE_SENSOR_WAR_CTS 0xFF02010A -#define OID_SKGE_SENSOR_ERR_CTS 0xFF02010B -#define OID_SKGE_SENSOR_WAR_TIME 0xFF02010C -#define OID_SKGE_SENSOR_ERR_TIME 0xFF02010D - -#define OID_SKGE_CHKSM_NUMBER 0xFF020110 -#define OID_SKGE_CHKSM_RX_OK_CTS 0xFF020111 -#define OID_SKGE_CHKSM_RX_UNABLE_CTS 0xFF020112 -#define OID_SKGE_CHKSM_RX_ERR_CTS 0xFF020113 -#define OID_SKGE_CHKSM_TX_OK_CTS 0xFF020114 -#define OID_SKGE_CHKSM_TX_UNABLE_CTS 0xFF020115 - -#define OID_SKGE_STAT_TX 0xFF020120 -#define OID_SKGE_STAT_TX_OCTETS 0xFF020121 -#define OID_SKGE_STAT_TX_BROADCAST 0xFF020122 -#define OID_SKGE_STAT_TX_MULTICAST 0xFF020123 -#define OID_SKGE_STAT_TX_UNICAST 0xFF020124 -#define OID_SKGE_STAT_TX_LONGFRAMES 0xFF020125 -#define OID_SKGE_STAT_TX_BURST 0xFF020126 -#define OID_SKGE_STAT_TX_PFLOWC 0xFF020127 -#define OID_SKGE_STAT_TX_FLOWC 0xFF020128 -#define OID_SKGE_STAT_TX_SINGLE_COL 0xFF020129 -#define OID_SKGE_STAT_TX_MULTI_COL 0xFF02012A -#define OID_SKGE_STAT_TX_EXCESS_COL 0xFF02012B -#define OID_SKGE_STAT_TX_LATE_COL 0xFF02012C -#define OID_SKGE_STAT_TX_DEFFERAL 0xFF02012D -#define OID_SKGE_STAT_TX_EXCESS_DEF 0xFF02012E -#define OID_SKGE_STAT_TX_UNDERRUN 0xFF02012F -#define OID_SKGE_STAT_TX_CARRIER 0xFF020130 -/* #define OID_SKGE_STAT_TX_UTIL 0xFF020131 */ -#define OID_SKGE_STAT_TX_64 0xFF020132 -#define OID_SKGE_STAT_TX_127 0xFF020133 -#define OID_SKGE_STAT_TX_255 0xFF020134 -#define OID_SKGE_STAT_TX_511 0xFF020135 -#define OID_SKGE_STAT_TX_1023 0xFF020136 -#define OID_SKGE_STAT_TX_MAX 0xFF020137 -#define OID_SKGE_STAT_TX_SYNC 0xFF020138 -#define OID_SKGE_STAT_TX_SYNC_OCTETS 0xFF020139 -#define OID_SKGE_STAT_RX 0xFF02013A -#define OID_SKGE_STAT_RX_OCTETS 0xFF02013B -#define OID_SKGE_STAT_RX_BROADCAST 0xFF02013C -#define OID_SKGE_STAT_RX_MULTICAST 0xFF02013D -#define OID_SKGE_STAT_RX_UNICAST 0xFF02013E -#define OID_SKGE_STAT_RX_PFLOWC 0xFF02013F -#define OID_SKGE_STAT_RX_FLOWC 0xFF020140 -#define OID_SKGE_STAT_RX_PFLOWC_ERR 0xFF020141 -#define OID_SKGE_STAT_RX_FLOWC_UNKWN 0xFF020142 -#define OID_SKGE_STAT_RX_BURST 0xFF020143 -#define OID_SKGE_STAT_RX_MISSED 0xFF020144 -#define OID_SKGE_STAT_RX_FRAMING 0xFF020145 -#define OID_SKGE_STAT_RX_OVERFLOW 0xFF020146 -#define OID_SKGE_STAT_RX_JABBER 0xFF020147 -#define OID_SKGE_STAT_RX_CARRIER 0xFF020148 -#define OID_SKGE_STAT_RX_IR_LENGTH 0xFF020149 -#define OID_SKGE_STAT_RX_SYMBOL 0xFF02014A -#define OID_SKGE_STAT_RX_SHORTS 0xFF02014B -#define OID_SKGE_STAT_RX_RUNT 0xFF02014C -#define OID_SKGE_STAT_RX_CEXT 0xFF02014D -#define OID_SKGE_STAT_RX_TOO_LONG 0xFF02014E -#define OID_SKGE_STAT_RX_FCS 0xFF02014F -/* #define OID_SKGE_STAT_RX_UTIL 0xFF020150 */ -#define OID_SKGE_STAT_RX_64 0xFF020151 -#define OID_SKGE_STAT_RX_127 0xFF020152 -#define OID_SKGE_STAT_RX_255 0xFF020153 -#define OID_SKGE_STAT_RX_511 0xFF020154 -#define OID_SKGE_STAT_RX_1023 0xFF020155 -#define OID_SKGE_STAT_RX_MAX 0xFF020156 -#define OID_SKGE_STAT_RX_LONGFRAMES 0xFF020157 - -#define OID_SKGE_RLMT_CHANGE_CTS 0xFF020160 -#define OID_SKGE_RLMT_CHANGE_TIME 0xFF020161 -#define OID_SKGE_RLMT_CHANGE_ESTIM 0xFF020162 -#define OID_SKGE_RLMT_CHANGE_THRES 0xFF020163 - -#define OID_SKGE_RLMT_PORT_INDEX 0xFF020164 -#define OID_SKGE_RLMT_STATUS 0xFF020165 -#define OID_SKGE_RLMT_TX_HELLO_CTS 0xFF020166 -#define OID_SKGE_RLMT_RX_HELLO_CTS 0xFF020167 -#define OID_SKGE_RLMT_TX_SP_REQ_CTS 0xFF020168 -#define OID_SKGE_RLMT_RX_SP_CTS 0xFF020169 - -#define OID_SKGE_RLMT_MONITOR_NUMBER 0xFF010150 -#define OID_SKGE_RLMT_MONITOR_INDEX 0xFF010151 -#define OID_SKGE_RLMT_MONITOR_ADDR 0xFF010152 -#define OID_SKGE_RLMT_MONITOR_ERRS 0xFF010153 -#define OID_SKGE_RLMT_MONITOR_TIMESTAMP 0xFF010154 -#define OID_SKGE_RLMT_MONITOR_ADMIN 0xFF010155 - -#define OID_SKGE_TX_SW_QUEUE_LEN 0xFF020170 -#define OID_SKGE_TX_SW_QUEUE_MAX 0xFF020171 -#define OID_SKGE_TX_RETRY 0xFF020172 -#define OID_SKGE_RX_INTR_CTS 0xFF020173 -#define OID_SKGE_TX_INTR_CTS 0xFF020174 -#define OID_SKGE_RX_NO_BUF_CTS 0xFF020175 -#define OID_SKGE_TX_NO_BUF_CTS 0xFF020176 -#define OID_SKGE_TX_USED_DESCR_NO 0xFF020177 -#define OID_SKGE_RX_DELIVERED_CTS 0xFF020178 -#define OID_SKGE_RX_OCTETS_DELIV_CTS 0xFF020179 -#define OID_SKGE_RX_HW_ERROR_CTS 0xFF02017A -#define OID_SKGE_TX_HW_ERROR_CTS 0xFF02017B -#define OID_SKGE_IN_ERRORS_CTS 0xFF02017C -#define OID_SKGE_OUT_ERROR_CTS 0xFF02017D -#define OID_SKGE_ERR_RECOVERY_CTS 0xFF02017E -#define OID_SKGE_SYSUPTIME 0xFF02017F - -#define OID_SKGE_ALL_DATA 0xFF020190 - -/* Defines for VCT. */ -#define OID_SKGE_VCT_GET 0xFF020200 -#define OID_SKGE_VCT_SET 0xFF020201 -#define OID_SKGE_VCT_STATUS 0xFF020202 - -#ifdef SK_DIAG_SUPPORT -/* Defines for driver DIAG mode. */ -#define OID_SKGE_DIAG_MODE 0xFF020204 -#endif /* SK_DIAG_SUPPORT */ - -/* New OIDs */ -#define OID_SKGE_DRIVER_RELDATE 0xFF020210 -#define OID_SKGE_DRIVER_FILENAME 0xFF020211 -#define OID_SKGE_CHIPID 0xFF020212 -#define OID_SKGE_RAMSIZE 0xFF020213 -#define OID_SKGE_VAUXAVAIL 0xFF020214 -#define OID_SKGE_PHY_TYPE 0xFF020215 -#define OID_SKGE_PHY_LP_MODE 0xFF020216 - -/* VCT struct to store a backup copy of VCT data after a port reset. */ -typedef struct s_PnmiVct { - SK_U8 VctStatus; - SK_U8 PCableLen; - SK_U32 PMdiPairLen[4]; - SK_U8 PMdiPairSts[4]; -} SK_PNMI_VCT; - - -/* VCT status values (to be given to CPA via OID_SKGE_VCT_STATUS). */ -#define SK_PNMI_VCT_NONE 0 -#define SK_PNMI_VCT_OLD_VCT_DATA 1 -#define SK_PNMI_VCT_NEW_VCT_DATA 2 -#define SK_PNMI_VCT_OLD_DSP_DATA 4 -#define SK_PNMI_VCT_NEW_DSP_DATA 8 -#define SK_PNMI_VCT_RUNNING 16 - - -/* VCT cable test status. */ -#define SK_PNMI_VCT_NORMAL_CABLE 0 -#define SK_PNMI_VCT_SHORT_CABLE 1 -#define SK_PNMI_VCT_OPEN_CABLE 2 -#define SK_PNMI_VCT_TEST_FAIL 3 -#define SK_PNMI_VCT_IMPEDANCE_MISMATCH 4 - -#define OID_SKGE_TRAP_SEN_WAR_LOW 500 -#define OID_SKGE_TRAP_SEN_WAR_UPP 501 -#define OID_SKGE_TRAP_SEN_ERR_LOW 502 -#define OID_SKGE_TRAP_SEN_ERR_UPP 503 -#define OID_SKGE_TRAP_RLMT_CHANGE_THRES 520 -#define OID_SKGE_TRAP_RLMT_CHANGE_PORT 521 -#define OID_SKGE_TRAP_RLMT_PORT_DOWN 522 -#define OID_SKGE_TRAP_RLMT_PORT_UP 523 -#define OID_SKGE_TRAP_RLMT_SEGMENTATION 524 - -#ifdef SK_DIAG_SUPPORT -/* Defines for driver DIAG mode. */ -#define SK_DIAG_ATTACHED 2 -#define SK_DIAG_RUNNING 1 -#define SK_DIAG_IDLE 0 -#endif /* SK_DIAG_SUPPORT */ - -/* - * Generic PNMI IOCTL subcommand definitions. - */ -#define SK_GET_SINGLE_VAR 1 -#define SK_SET_SINGLE_VAR 2 -#define SK_PRESET_SINGLE_VAR 3 -#define SK_GET_FULL_MIB 4 -#define SK_SET_FULL_MIB 5 -#define SK_PRESET_FULL_MIB 6 - - -/* - * Define error numbers and messages for syslog - */ -#define SK_PNMI_ERR001 (SK_ERRBASE_PNMI + 1) -#define SK_PNMI_ERR001MSG "SkPnmiGetStruct: Unknown OID" -#define SK_PNMI_ERR002 (SK_ERRBASE_PNMI + 2) -#define SK_PNMI_ERR002MSG "SkPnmiGetStruct: Cannot read VPD keys" -#define SK_PNMI_ERR003 (SK_ERRBASE_PNMI + 3) -#define SK_PNMI_ERR003MSG "OidStruct: Called with wrong OID" -#define SK_PNMI_ERR004 (SK_ERRBASE_PNMI + 4) -#define SK_PNMI_ERR004MSG "OidStruct: Called with wrong action" -#define SK_PNMI_ERR005 (SK_ERRBASE_PNMI + 5) -#define SK_PNMI_ERR005MSG "Perform: Cannot reset driver" -#define SK_PNMI_ERR006 (SK_ERRBASE_PNMI + 6) -#define SK_PNMI_ERR006MSG "Perform: Unknown OID action command" -#define SK_PNMI_ERR007 (SK_ERRBASE_PNMI + 7) -#define SK_PNMI_ERR007MSG "General: Driver description not initialized" -#define SK_PNMI_ERR008 (SK_ERRBASE_PNMI + 8) -#define SK_PNMI_ERR008MSG "Addr: Tried to get unknown OID" -#define SK_PNMI_ERR009 (SK_ERRBASE_PNMI + 9) -#define SK_PNMI_ERR009MSG "Addr: Unknown OID" -#define SK_PNMI_ERR010 (SK_ERRBASE_PNMI + 10) -#define SK_PNMI_ERR010MSG "CsumStat: Unknown OID" -#define SK_PNMI_ERR011 (SK_ERRBASE_PNMI + 11) -#define SK_PNMI_ERR011MSG "SensorStat: Sensor descr string too long" -#define SK_PNMI_ERR012 (SK_ERRBASE_PNMI + 12) -#define SK_PNMI_ERR012MSG "SensorStat: Unknown OID" -#define SK_PNMI_ERR013 (SK_ERRBASE_PNMI + 13) -#define SK_PNMI_ERR013MSG "" -#define SK_PNMI_ERR014 (SK_ERRBASE_PNMI + 14) -#define SK_PNMI_ERR014MSG "Vpd: Cannot read VPD keys" -#define SK_PNMI_ERR015 (SK_ERRBASE_PNMI + 15) -#define SK_PNMI_ERR015MSG "Vpd: Internal array for VPD keys to small" -#define SK_PNMI_ERR016 (SK_ERRBASE_PNMI + 16) -#define SK_PNMI_ERR016MSG "Vpd: Key string too long" -#define SK_PNMI_ERR017 (SK_ERRBASE_PNMI + 17) -#define SK_PNMI_ERR017MSG "Vpd: Invalid VPD status pointer" -#define SK_PNMI_ERR018 (SK_ERRBASE_PNMI + 18) -#define SK_PNMI_ERR018MSG "Vpd: VPD data not valid" -#define SK_PNMI_ERR019 (SK_ERRBASE_PNMI + 19) -#define SK_PNMI_ERR019MSG "Vpd: VPD entries list string too long" -#define SK_PNMI_ERR021 (SK_ERRBASE_PNMI + 21) -#define SK_PNMI_ERR021MSG "Vpd: VPD data string too long" -#define SK_PNMI_ERR022 (SK_ERRBASE_PNMI + 22) -#define SK_PNMI_ERR022MSG "Vpd: VPD data string too long should be errored before" -#define SK_PNMI_ERR023 (SK_ERRBASE_PNMI + 23) -#define SK_PNMI_ERR023MSG "Vpd: Unknown OID in get action" -#define SK_PNMI_ERR024 (SK_ERRBASE_PNMI + 24) -#define SK_PNMI_ERR024MSG "Vpd: Unknown OID in preset/set action" -#define SK_PNMI_ERR025 (SK_ERRBASE_PNMI + 25) -#define SK_PNMI_ERR025MSG "Vpd: Cannot write VPD after modify entry" -#define SK_PNMI_ERR026 (SK_ERRBASE_PNMI + 26) -#define SK_PNMI_ERR026MSG "Vpd: Cannot update VPD" -#define SK_PNMI_ERR027 (SK_ERRBASE_PNMI + 27) -#define SK_PNMI_ERR027MSG "Vpd: Cannot delete VPD entry" -#define SK_PNMI_ERR028 (SK_ERRBASE_PNMI + 28) -#define SK_PNMI_ERR028MSG "Vpd: Cannot update VPD after delete entry" -#define SK_PNMI_ERR029 (SK_ERRBASE_PNMI + 29) -#define SK_PNMI_ERR029MSG "General: Driver description string too long" -#define SK_PNMI_ERR030 (SK_ERRBASE_PNMI + 30) -#define SK_PNMI_ERR030MSG "General: Driver version not initialized" -#define SK_PNMI_ERR031 (SK_ERRBASE_PNMI + 31) -#define SK_PNMI_ERR031MSG "General: Driver version string too long" -#define SK_PNMI_ERR032 (SK_ERRBASE_PNMI + 32) -#define SK_PNMI_ERR032MSG "General: Cannot read VPD Name for HW descr" -#define SK_PNMI_ERR033 (SK_ERRBASE_PNMI + 33) -#define SK_PNMI_ERR033MSG "General: HW description string too long" -#define SK_PNMI_ERR034 (SK_ERRBASE_PNMI + 34) -#define SK_PNMI_ERR034MSG "General: Unknown OID" -#define SK_PNMI_ERR035 (SK_ERRBASE_PNMI + 35) -#define SK_PNMI_ERR035MSG "Rlmt: Unknown OID" -#define SK_PNMI_ERR036 (SK_ERRBASE_PNMI + 36) -#define SK_PNMI_ERR036MSG "" -#define SK_PNMI_ERR037 (SK_ERRBASE_PNMI + 37) -#define SK_PNMI_ERR037MSG "Rlmt: SK_RLMT_MODE_CHANGE event return not 0" -#define SK_PNMI_ERR038 (SK_ERRBASE_PNMI + 38) -#define SK_PNMI_ERR038MSG "Rlmt: SK_RLMT_PREFPORT_CHANGE event return not 0" -#define SK_PNMI_ERR039 (SK_ERRBASE_PNMI + 39) -#define SK_PNMI_ERR039MSG "RlmtStat: Unknown OID" -#define SK_PNMI_ERR040 (SK_ERRBASE_PNMI + 40) -#define SK_PNMI_ERR040MSG "PowerManagement: Unknown OID" -#define SK_PNMI_ERR041 (SK_ERRBASE_PNMI + 41) -#define SK_PNMI_ERR041MSG "MacPrivateConf: Unknown OID" -#define SK_PNMI_ERR042 (SK_ERRBASE_PNMI + 42) -#define SK_PNMI_ERR042MSG "MacPrivateConf: SK_HWEV_SET_ROLE returned not 0" -#define SK_PNMI_ERR043 (SK_ERRBASE_PNMI + 43) -#define SK_PNMI_ERR043MSG "MacPrivateConf: SK_HWEV_SET_LMODE returned not 0" -#define SK_PNMI_ERR044 (SK_ERRBASE_PNMI + 44) -#define SK_PNMI_ERR044MSG "MacPrivateConf: SK_HWEV_SET_FLOWMODE returned not 0" -#define SK_PNMI_ERR045 (SK_ERRBASE_PNMI + 45) -#define SK_PNMI_ERR045MSG "MacPrivateConf: SK_HWEV_SET_SPEED returned not 0" -#define SK_PNMI_ERR046 (SK_ERRBASE_PNMI + 46) -#define SK_PNMI_ERR046MSG "Monitor: Unknown OID" -#define SK_PNMI_ERR047 (SK_ERRBASE_PNMI + 47) -#define SK_PNMI_ERR047MSG "SirqUpdate: Event function returns not 0" -#define SK_PNMI_ERR048 (SK_ERRBASE_PNMI + 48) -#define SK_PNMI_ERR048MSG "RlmtUpdate: Event function returns not 0" -#define SK_PNMI_ERR049 (SK_ERRBASE_PNMI + 49) -#define SK_PNMI_ERR049MSG "SkPnmiInit: Invalid size of 'CounterOffset' struct!!" -#define SK_PNMI_ERR050 (SK_ERRBASE_PNMI + 50) -#define SK_PNMI_ERR050MSG "SkPnmiInit: Invalid size of 'StatAddr' table!!" -#define SK_PNMI_ERR051 (SK_ERRBASE_PNMI + 51) -#define SK_PNMI_ERR051MSG "SkPnmiEvent: Port switch suspicious" -#define SK_PNMI_ERR052 (SK_ERRBASE_PNMI + 52) -#define SK_PNMI_ERR052MSG "" -#define SK_PNMI_ERR053 (SK_ERRBASE_PNMI + 53) -#define SK_PNMI_ERR053MSG "General: Driver release date not initialized" -#define SK_PNMI_ERR054 (SK_ERRBASE_PNMI + 54) -#define SK_PNMI_ERR054MSG "General: Driver release date string too long" -#define SK_PNMI_ERR055 (SK_ERRBASE_PNMI + 55) -#define SK_PNMI_ERR055MSG "General: Driver file name not initialized" -#define SK_PNMI_ERR056 (SK_ERRBASE_PNMI + 56) -#define SK_PNMI_ERR056MSG "General: Driver file name string too long" - -/* - * Management counter macros called by the driver - */ -#define SK_PNMI_SET_DRIVER_DESCR(pAC,v) ((pAC)->Pnmi.pDriverDescription = \ - (char *)(v)) - -#define SK_PNMI_SET_DRIVER_VER(pAC,v) ((pAC)->Pnmi.pDriverVersion = \ - (char *)(v)) - -#define SK_PNMI_SET_DRIVER_RELDATE(pAC,v) ((pAC)->Pnmi.pDriverReleaseDate = \ - (char *)(v)) - -#define SK_PNMI_SET_DRIVER_FILENAME(pAC,v) ((pAC)->Pnmi.pDriverFileName = \ - (char *)(v)) - -#define SK_PNMI_CNT_TX_QUEUE_LEN(pAC,v,p) \ - { \ - (pAC)->Pnmi.Port[p].TxSwQueueLen = (SK_U64)(v); \ - if ((pAC)->Pnmi.Port[p].TxSwQueueLen > (pAC)->Pnmi.Port[p].TxSwQueueMax) { \ - (pAC)->Pnmi.Port[p].TxSwQueueMax = (pAC)->Pnmi.Port[p].TxSwQueueLen; \ - } \ - } -#define SK_PNMI_CNT_TX_RETRY(pAC,p) (((pAC)->Pnmi.Port[p].TxRetryCts)++) -#define SK_PNMI_CNT_RX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].RxIntrCts)++) -#define SK_PNMI_CNT_TX_INTR(pAC,p) (((pAC)->Pnmi.Port[p].TxIntrCts)++) -#define SK_PNMI_CNT_NO_RX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].RxNoBufCts)++) -#define SK_PNMI_CNT_NO_TX_BUF(pAC,p) (((pAC)->Pnmi.Port[p].TxNoBufCts)++) -#define SK_PNMI_CNT_USED_TX_DESCR(pAC,v,p) \ - ((pAC)->Pnmi.Port[p].TxUsedDescrNo=(SK_U64)(v)); -#define SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC,v,p) \ - { \ - ((pAC)->Pnmi.Port[p].RxDeliveredCts)++; \ - (pAC)->Pnmi.Port[p].RxOctetsDeliveredCts += (SK_U64)(v); \ - } -#define SK_PNMI_CNT_ERR_RECOVERY(pAC,p) (((pAC)->Pnmi.Port[p].ErrRecoveryCts)++); - -#define SK_PNMI_CNT_SYNC_OCTETS(pAC,p,v) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatSyncCts)++; \ - (pAC)->Pnmi.Port[p].StatSyncOctetsCts += (SK_U64)(v); \ - } \ - } - -#define SK_PNMI_CNT_RX_LONGFRAMES(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxLongFrameCts++); \ - } \ - } - -#define SK_PNMI_CNT_RX_FRAMETOOLONG(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxFrameTooLongCts++); \ - } \ - } - -#define SK_PNMI_CNT_RX_PMACC_ERR(pAC,p) \ - { \ - if ((p) < SK_MAX_MACS) { \ - ((pAC)->Pnmi.Port[p].StatRxPMaccErr++); \ - } \ - } - -/* - * Conversion Macros - */ -#define SK_PNMI_PORT_INST2LOG(i) ((unsigned int)(i) - 1) -#define SK_PNMI_PORT_LOG2INST(l) ((unsigned int)(l) + 1) -#define SK_PNMI_PORT_PHYS2LOG(p) ((unsigned int)(p) + 1) -#define SK_PNMI_PORT_LOG2PHYS(pAC,l) ((unsigned int)(l) - 1) -#define SK_PNMI_PORT_PHYS2INST(pAC,p) \ - (pAC->Pnmi.DualNetActiveFlag ? 2 : ((unsigned int)(p) + 2)) -#define SK_PNMI_PORT_INST2PHYS(pAC,i) ((unsigned int)(i) - 2) - -/* - * Structure definition for SkPnmiGetStruct and SkPnmiSetStruct - */ -#define SK_PNMI_VPD_KEY_SIZE 5 -#define SK_PNMI_VPD_BUFSIZE (VPD_SIZE) -#define SK_PNMI_VPD_ENTRIES (VPD_SIZE / 4) -#define SK_PNMI_VPD_DATALEN 128 /* Number of data bytes */ - -#define SK_PNMI_MULTICAST_LISTLEN 64 -#define SK_PNMI_SENSOR_ENTRIES (SK_MAX_SENSORS) -#define SK_PNMI_CHECKSUM_ENTRIES 3 -#define SK_PNMI_MAC_ENTRIES (SK_MAX_MACS + 1) -#define SK_PNMI_MONITOR_ENTRIES 20 -#define SK_PNMI_TRAP_ENTRIES 10 -#define SK_PNMI_TRAPLEN 128 -#define SK_PNMI_STRINGLEN1 80 -#define SK_PNMI_STRINGLEN2 25 -#define SK_PNMI_TRAP_QUEUE_LEN 512 - -typedef struct s_PnmiVpd { - char VpdKey[SK_PNMI_VPD_KEY_SIZE]; - char VpdValue[SK_PNMI_VPD_DATALEN]; - SK_U8 VpdAccess; - SK_U8 VpdAction; -} SK_PNMI_VPD; - -typedef struct s_PnmiSensor { - SK_U8 SensorIndex; - char SensorDescr[SK_PNMI_STRINGLEN2]; - SK_U8 SensorType; - SK_U32 SensorValue; - SK_U32 SensorWarningThresholdLow; - SK_U32 SensorWarningThresholdHigh; - SK_U32 SensorErrorThresholdLow; - SK_U32 SensorErrorThresholdHigh; - SK_U8 SensorStatus; - SK_U64 SensorWarningCts; - SK_U64 SensorErrorCts; - SK_U64 SensorWarningTimestamp; - SK_U64 SensorErrorTimestamp; -} SK_PNMI_SENSOR; - -typedef struct s_PnmiChecksum { - SK_U64 ChecksumRxOkCts; - SK_U64 ChecksumRxUnableCts; - SK_U64 ChecksumRxErrCts; - SK_U64 ChecksumTxOkCts; - SK_U64 ChecksumTxUnableCts; -} SK_PNMI_CHECKSUM; - -typedef struct s_PnmiStat { - SK_U64 StatTxOkCts; - SK_U64 StatTxOctetsOkCts; - SK_U64 StatTxBroadcastOkCts; - SK_U64 StatTxMulticastOkCts; - SK_U64 StatTxUnicastOkCts; - SK_U64 StatTxLongFramesCts; - SK_U64 StatTxBurstCts; - SK_U64 StatTxPauseMacCtrlCts; - SK_U64 StatTxMacCtrlCts; - SK_U64 StatTxSingleCollisionCts; - SK_U64 StatTxMultipleCollisionCts; - SK_U64 StatTxExcessiveCollisionCts; - SK_U64 StatTxLateCollisionCts; - SK_U64 StatTxDeferralCts; - SK_U64 StatTxExcessiveDeferralCts; - SK_U64 StatTxFifoUnderrunCts; - SK_U64 StatTxCarrierCts; - SK_U64 Dummy1; /* StatTxUtilization */ - SK_U64 StatTx64Cts; - SK_U64 StatTx127Cts; - SK_U64 StatTx255Cts; - SK_U64 StatTx511Cts; - SK_U64 StatTx1023Cts; - SK_U64 StatTxMaxCts; - SK_U64 StatTxSyncCts; - SK_U64 StatTxSyncOctetsCts; - SK_U64 StatRxOkCts; - SK_U64 StatRxOctetsOkCts; - SK_U64 StatRxBroadcastOkCts; - SK_U64 StatRxMulticastOkCts; - SK_U64 StatRxUnicastOkCts; - SK_U64 StatRxLongFramesCts; - SK_U64 StatRxPauseMacCtrlCts; - SK_U64 StatRxMacCtrlCts; - SK_U64 StatRxPauseMacCtrlErrorCts; - SK_U64 StatRxMacCtrlUnknownCts; - SK_U64 StatRxBurstCts; - SK_U64 StatRxMissedCts; - SK_U64 StatRxFramingCts; - SK_U64 StatRxFifoOverflowCts; - SK_U64 StatRxJabberCts; - SK_U64 StatRxCarrierCts; - SK_U64 StatRxIRLengthCts; - SK_U64 StatRxSymbolCts; - SK_U64 StatRxShortsCts; - SK_U64 StatRxRuntCts; - SK_U64 StatRxCextCts; - SK_U64 StatRxTooLongCts; - SK_U64 StatRxFcsCts; - SK_U64 Dummy2; /* StatRxUtilization */ - SK_U64 StatRx64Cts; - SK_U64 StatRx127Cts; - SK_U64 StatRx255Cts; - SK_U64 StatRx511Cts; - SK_U64 StatRx1023Cts; - SK_U64 StatRxMaxCts; -} SK_PNMI_STAT; - -typedef struct s_PnmiConf { - char ConfMacCurrentAddr[6]; - char ConfMacFactoryAddr[6]; - SK_U8 ConfPMD; - SK_U8 ConfConnector; - SK_U32 ConfPhyType; - SK_U32 ConfPhyMode; - SK_U8 ConfLinkCapability; - SK_U8 ConfLinkMode; - SK_U8 ConfLinkModeStatus; - SK_U8 ConfLinkStatus; - SK_U8 ConfFlowCtrlCapability; - SK_U8 ConfFlowCtrlMode; - SK_U8 ConfFlowCtrlStatus; - SK_U8 ConfPhyOperationCapability; - SK_U8 ConfPhyOperationMode; - SK_U8 ConfPhyOperationStatus; - SK_U8 ConfSpeedCapability; - SK_U8 ConfSpeedMode; - SK_U8 ConfSpeedStatus; -} SK_PNMI_CONF; - -typedef struct s_PnmiRlmt { - SK_U32 RlmtIndex; - SK_U32 RlmtStatus; - SK_U64 RlmtTxHelloCts; - SK_U64 RlmtRxHelloCts; - SK_U64 RlmtTxSpHelloReqCts; - SK_U64 RlmtRxSpHelloCts; -} SK_PNMI_RLMT; - -typedef struct s_PnmiRlmtMonitor { - SK_U32 RlmtMonitorIndex; - char RlmtMonitorAddr[6]; - SK_U64 RlmtMonitorErrorCts; - SK_U64 RlmtMonitorTimestamp; - SK_U8 RlmtMonitorAdmin; -} SK_PNMI_RLMT_MONITOR; - -typedef struct s_PnmiRequestStatus { - SK_U32 ErrorStatus; - SK_U32 ErrorOffset; -} SK_PNMI_REQUEST_STATUS; - -typedef struct s_PnmiStrucData { - SK_U32 MgmtDBVersion; - SK_PNMI_REQUEST_STATUS ReturnStatus; - SK_U32 VpdFreeBytes; - char VpdEntriesList[SK_PNMI_VPD_ENTRIES * SK_PNMI_VPD_KEY_SIZE]; - SK_U32 VpdEntriesNumber; - SK_PNMI_VPD Vpd[SK_PNMI_VPD_ENTRIES]; - SK_U32 PortNumber; - SK_U32 DeviceType; - char DriverDescr[SK_PNMI_STRINGLEN1]; - char DriverVersion[SK_PNMI_STRINGLEN2]; - char DriverReleaseDate[SK_PNMI_STRINGLEN1]; - char DriverFileName[SK_PNMI_STRINGLEN1]; - char HwDescr[SK_PNMI_STRINGLEN1]; - char HwVersion[SK_PNMI_STRINGLEN2]; - SK_U16 Chipset; - SK_U32 ChipId; - SK_U8 VauxAvail; - SK_U32 RamSize; - SK_U32 MtuSize; - SK_U32 Action; - SK_U32 TestResult; - SK_U8 BusType; - SK_U8 BusSpeed; - SK_U8 BusWidth; - SK_U8 SensorNumber; - SK_PNMI_SENSOR Sensor[SK_PNMI_SENSOR_ENTRIES]; - SK_U8 ChecksumNumber; - SK_PNMI_CHECKSUM Checksum[SK_PNMI_CHECKSUM_ENTRIES]; - SK_PNMI_STAT Stat[SK_PNMI_MAC_ENTRIES]; - SK_PNMI_CONF Conf[SK_PNMI_MAC_ENTRIES]; - SK_U8 RlmtMode; - SK_U32 RlmtPortNumber; - SK_U8 RlmtPortActive; - SK_U8 RlmtPortPreferred; - SK_U64 RlmtChangeCts; - SK_U64 RlmtChangeTime; - SK_U64 RlmtChangeEstimate; - SK_U64 RlmtChangeThreshold; - SK_PNMI_RLMT Rlmt[SK_MAX_MACS]; - SK_U32 RlmtMonitorNumber; - SK_PNMI_RLMT_MONITOR RlmtMonitor[SK_PNMI_MONITOR_ENTRIES]; - SK_U32 TrapNumber; - SK_U8 Trap[SK_PNMI_TRAP_QUEUE_LEN]; - SK_U64 TxSwQueueLen; - SK_U64 TxSwQueueMax; - SK_U64 TxRetryCts; - SK_U64 RxIntrCts; - SK_U64 TxIntrCts; - SK_U64 RxNoBufCts; - SK_U64 TxNoBufCts; - SK_U64 TxUsedDescrNo; - SK_U64 RxDeliveredCts; - SK_U64 RxOctetsDeliveredCts; - SK_U64 RxHwErrorsCts; - SK_U64 TxHwErrorsCts; - SK_U64 InErrorsCts; - SK_U64 OutErrorsCts; - SK_U64 ErrRecoveryCts; - SK_U64 SysUpTime; -} SK_PNMI_STRUCT_DATA; - -#define SK_PNMI_STRUCT_SIZE (sizeof(SK_PNMI_STRUCT_DATA)) -#define SK_PNMI_MIN_STRUCT_SIZE ((unsigned int)(SK_UPTR)\ - &(((SK_PNMI_STRUCT_DATA *)0)->VpdFreeBytes)) - /* - * ReturnStatus field - * must be located - * before VpdFreeBytes - */ - -/* - * Various definitions - */ -#define SK_PNMI_MAX_PROTOS 3 - -#define SK_PNMI_CNT_NO 66 /* Must have the value of the enum - * SK_PNMI_MAX_IDX. Define SK_PNMI_CHECK - * for check while init phase 1 - */ - -/* - * Estimate data structure - */ -typedef struct s_PnmiEstimate { - unsigned int EstValueIndex; - SK_U64 EstValue[7]; - SK_U64 Estimate; - SK_TIMER EstTimer; -} SK_PNMI_ESTIMATE; - - -/* - * VCT timer data structure - */ -typedef struct s_VctTimer { - SK_TIMER VctTimer; -} SK_PNMI_VCT_TIMER; - - -/* - * PNMI specific adapter context structure - */ -typedef struct s_PnmiPort { - SK_U64 StatSyncCts; - SK_U64 StatSyncOctetsCts; - SK_U64 StatRxLongFrameCts; - SK_U64 StatRxFrameTooLongCts; - SK_U64 StatRxPMaccErr; - SK_U64 TxSwQueueLen; - SK_U64 TxSwQueueMax; - SK_U64 TxRetryCts; - SK_U64 RxIntrCts; - SK_U64 TxIntrCts; - SK_U64 RxNoBufCts; - SK_U64 TxNoBufCts; - SK_U64 TxUsedDescrNo; - SK_U64 RxDeliveredCts; - SK_U64 RxOctetsDeliveredCts; - SK_U64 RxHwErrorsCts; - SK_U64 TxHwErrorsCts; - SK_U64 InErrorsCts; - SK_U64 OutErrorsCts; - SK_U64 ErrRecoveryCts; - SK_U64 RxShortZeroMark; - SK_U64 CounterOffset[SK_PNMI_CNT_NO]; - SK_U32 CounterHigh[SK_PNMI_CNT_NO]; - SK_BOOL ActiveFlag; - SK_U8 Align[3]; -} SK_PNMI_PORT; - - -typedef struct s_PnmiData { - SK_PNMI_PORT Port [SK_MAX_MACS]; - SK_PNMI_PORT BufPort [SK_MAX_MACS]; /* 2002-09-13 pweber */ - SK_U64 VirtualCounterOffset[SK_PNMI_CNT_NO]; - SK_U32 TestResult; - char HwVersion[10]; - SK_U16 Align01; - - char *pDriverDescription; - char *pDriverVersion; - char *pDriverReleaseDate; - char *pDriverFileName; - - int MacUpdatedFlag; - int RlmtUpdatedFlag; - int SirqUpdatedFlag; - - SK_U64 RlmtChangeCts; - SK_U64 RlmtChangeTime; - SK_PNMI_ESTIMATE RlmtChangeEstimate; - SK_U64 RlmtChangeThreshold; - - SK_U64 StartUpTime; - SK_U32 DeviceType; - char PciBusSpeed; - char PciBusWidth; - char Chipset; - char PMD; - char Connector; - SK_BOOL DualNetActiveFlag; - SK_U16 Align02; - - char TrapBuf[SK_PNMI_TRAP_QUEUE_LEN]; - unsigned int TrapBufFree; - unsigned int TrapQueueBeg; - unsigned int TrapQueueEnd; - unsigned int TrapBufPad; - unsigned int TrapUnique; - SK_U8 VctStatus[SK_MAX_MACS]; - SK_PNMI_VCT VctBackup[SK_MAX_MACS]; - SK_PNMI_VCT_TIMER VctTimeout[SK_MAX_MACS]; -#ifdef SK_DIAG_SUPPORT - SK_U32 DiagAttached; -#endif /* SK_DIAG_SUPPORT */ -} SK_PNMI; - - -/* - * Function prototypes - */ -extern int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int Level); -extern int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void* pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -extern int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void* pBuf, - unsigned int *pLen, SK_U32 NetIndex); -extern int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, - SK_EVPARA Param); -extern int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf, - unsigned int * pLen, SK_U32 NetIndex); - -#endif diff --git a/drivers/net/sk98lin/h/skgesirq.h b/drivers/net/sk98lin/h/skgesirq.h deleted file mode 100644 index 3eec6274e413..000000000000 --- a/drivers/net/sk98lin/h/skgesirq.h +++ /dev/null @@ -1,110 +0,0 @@ -/****************************************************************************** - * - * Name: skgesirq.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.30 $ - * Date: $Date: 2003/07/04 12:34:13 $ - * Purpose: SK specific Gigabit Ethernet special IRQ functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef _INC_SKGESIRQ_H_ -#define _INC_SKGESIRQ_H_ - -/* Define return codes of SkGePortCheckUp and CheckShort */ -#define SK_HW_PS_NONE 0 /* No action needed */ -#define SK_HW_PS_RESTART 1 /* Restart needed */ -#define SK_HW_PS_LINK 2 /* Link Up actions needed */ - -/* - * Define the Event the special IRQ/INI module can handle - */ -#define SK_HWEV_WATIM 1 /* Timeout for WA Errata #2 XMAC */ -#define SK_HWEV_PORT_START 2 /* Port Start Event by RLMT */ -#define SK_HWEV_PORT_STOP 3 /* Port Stop Event by RLMT */ -#define SK_HWEV_CLEAR_STAT 4 /* Clear Statistics by PNMI */ -#define SK_HWEV_UPDATE_STAT 5 /* Update Statistics by PNMI */ -#define SK_HWEV_SET_LMODE 6 /* Set Link Mode by PNMI */ -#define SK_HWEV_SET_FLOWMODE 7 /* Set Flow Control Mode by PNMI */ -#define SK_HWEV_SET_ROLE 8 /* Set Master/Slave (Role) by PNMI */ -#define SK_HWEV_SET_SPEED 9 /* Set Link Speed by PNMI */ -#define SK_HWEV_HALFDUP_CHK 10 /* Half Duplex Hangup Workaround */ - -#define SK_WA_ACT_TIME (5000000UL) /* 5 sec */ -#define SK_WA_INA_TIME (100000UL) /* 100 msec */ - -#define SK_HALFDUP_CHK_TIME (10000UL) /* 10 msec */ - -/* - * Define the error numbers and messages - */ -#define SKERR_SIRQ_E001 (SK_ERRBASE_SIRQ+0) -#define SKERR_SIRQ_E001MSG "Unknown event" -#define SKERR_SIRQ_E002 (SKERR_SIRQ_E001+1) -#define SKERR_SIRQ_E002MSG "Packet timeout RX1" -#define SKERR_SIRQ_E003 (SKERR_SIRQ_E002+1) -#define SKERR_SIRQ_E003MSG "Packet timeout RX2" -#define SKERR_SIRQ_E004 (SKERR_SIRQ_E003+1) -#define SKERR_SIRQ_E004MSG "MAC 1 not correctly initialized" -#define SKERR_SIRQ_E005 (SKERR_SIRQ_E004+1) -#define SKERR_SIRQ_E005MSG "MAC 2 not correctly initialized" -#define SKERR_SIRQ_E006 (SKERR_SIRQ_E005+1) -#define SKERR_SIRQ_E006MSG "CHECK failure R1" -#define SKERR_SIRQ_E007 (SKERR_SIRQ_E006+1) -#define SKERR_SIRQ_E007MSG "CHECK failure R2" -#define SKERR_SIRQ_E008 (SKERR_SIRQ_E007+1) -#define SKERR_SIRQ_E008MSG "CHECK failure XS1" -#define SKERR_SIRQ_E009 (SKERR_SIRQ_E008+1) -#define SKERR_SIRQ_E009MSG "CHECK failure XA1" -#define SKERR_SIRQ_E010 (SKERR_SIRQ_E009+1) -#define SKERR_SIRQ_E010MSG "CHECK failure XS2" -#define SKERR_SIRQ_E011 (SKERR_SIRQ_E010+1) -#define SKERR_SIRQ_E011MSG "CHECK failure XA2" -#define SKERR_SIRQ_E012 (SKERR_SIRQ_E011+1) -#define SKERR_SIRQ_E012MSG "unexpected IRQ Master error" -#define SKERR_SIRQ_E013 (SKERR_SIRQ_E012+1) -#define SKERR_SIRQ_E013MSG "unexpected IRQ Status error" -#define SKERR_SIRQ_E014 (SKERR_SIRQ_E013+1) -#define SKERR_SIRQ_E014MSG "Parity error on RAM (read)" -#define SKERR_SIRQ_E015 (SKERR_SIRQ_E014+1) -#define SKERR_SIRQ_E015MSG "Parity error on RAM (write)" -#define SKERR_SIRQ_E016 (SKERR_SIRQ_E015+1) -#define SKERR_SIRQ_E016MSG "Parity error MAC 1" -#define SKERR_SIRQ_E017 (SKERR_SIRQ_E016+1) -#define SKERR_SIRQ_E017MSG "Parity error MAC 2" -#define SKERR_SIRQ_E018 (SKERR_SIRQ_E017+1) -#define SKERR_SIRQ_E018MSG "Parity error RX 1" -#define SKERR_SIRQ_E019 (SKERR_SIRQ_E018+1) -#define SKERR_SIRQ_E019MSG "Parity error RX 2" -#define SKERR_SIRQ_E020 (SKERR_SIRQ_E019+1) -#define SKERR_SIRQ_E020MSG "MAC transmit FIFO underrun" -#define SKERR_SIRQ_E021 (SKERR_SIRQ_E020+1) -#define SKERR_SIRQ_E021MSG "Spurious TWSI interrupt" -#define SKERR_SIRQ_E022 (SKERR_SIRQ_E021+1) -#define SKERR_SIRQ_E022MSG "Cable pair swap error" -#define SKERR_SIRQ_E023 (SKERR_SIRQ_E022+1) -#define SKERR_SIRQ_E023MSG "Auto-negotiation error" -#define SKERR_SIRQ_E024 (SKERR_SIRQ_E023+1) -#define SKERR_SIRQ_E024MSG "FIFO overflow error" -#define SKERR_SIRQ_E025 (SKERR_SIRQ_E024+1) -#define SKERR_SIRQ_E025MSG "2 Pair Downshift detected" - -extern void SkGeSirqIsr(SK_AC *pAC, SK_IOC IoC, SK_U32 Istatus); -extern int SkGeSirqEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); -extern void SkHWLinkDown(SK_AC *pAC, SK_IOC IoC, int Port); - -#endif /* _INC_SKGESIRQ_H_ */ diff --git a/drivers/net/sk98lin/h/ski2c.h b/drivers/net/sk98lin/h/ski2c.h deleted file mode 100644 index 6a63f4a15de6..000000000000 --- a/drivers/net/sk98lin/h/ski2c.h +++ /dev/null @@ -1,174 +0,0 @@ -/****************************************************************************** - * - * Name: ski2c.h - * Project: Gigabit Ethernet Adapters, TWSI-Module - * Version: $Revision: 1.35 $ - * Date: $Date: 2003/10/20 09:06:30 $ - * Purpose: Defines to access Voltage and Temperature Sensor - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKI2C.H contains all I2C specific defines - */ - -#ifndef _SKI2C_H_ -#define _SKI2C_H_ - -typedef struct s_Sensor SK_SENSOR; - -#include "h/skgei2c.h" - -/* - * Define the I2C events. - */ -#define SK_I2CEV_IRQ 1 /* IRQ happened Event */ -#define SK_I2CEV_TIM 2 /* Timeout event */ -#define SK_I2CEV_CLEAR 3 /* Clear MIB Values */ - -/* - * Define READ and WRITE Constants. - */ -#define I2C_READ 0 -#define I2C_WRITE 1 -#define I2C_BURST 1 -#define I2C_SINGLE 0 - -#define SKERR_I2C_E001 (SK_ERRBASE_I2C+0) -#define SKERR_I2C_E001MSG "Sensor index unknown" -#define SKERR_I2C_E002 (SKERR_I2C_E001+1) -#define SKERR_I2C_E002MSG "TWSI: transfer does not complete" -#define SKERR_I2C_E003 (SKERR_I2C_E002+1) -#define SKERR_I2C_E003MSG "LM80: NAK on device send" -#define SKERR_I2C_E004 (SKERR_I2C_E003+1) -#define SKERR_I2C_E004MSG "LM80: NAK on register send" -#define SKERR_I2C_E005 (SKERR_I2C_E004+1) -#define SKERR_I2C_E005MSG "LM80: NAK on device (2) send" -#define SKERR_I2C_E006 (SKERR_I2C_E005+1) -#define SKERR_I2C_E006MSG "Unknown event" -#define SKERR_I2C_E007 (SKERR_I2C_E006+1) -#define SKERR_I2C_E007MSG "LM80 read out of state" -#define SKERR_I2C_E008 (SKERR_I2C_E007+1) -#define SKERR_I2C_E008MSG "Unexpected sensor read completed" -#define SKERR_I2C_E009 (SKERR_I2C_E008+1) -#define SKERR_I2C_E009MSG "WARNING: temperature sensor out of range" -#define SKERR_I2C_E010 (SKERR_I2C_E009+1) -#define SKERR_I2C_E010MSG "WARNING: voltage sensor out of range" -#define SKERR_I2C_E011 (SKERR_I2C_E010+1) -#define SKERR_I2C_E011MSG "ERROR: temperature sensor out of range" -#define SKERR_I2C_E012 (SKERR_I2C_E011+1) -#define SKERR_I2C_E012MSG "ERROR: voltage sensor out of range" -#define SKERR_I2C_E013 (SKERR_I2C_E012+1) -#define SKERR_I2C_E013MSG "ERROR: couldn't init sensor" -#define SKERR_I2C_E014 (SKERR_I2C_E013+1) -#define SKERR_I2C_E014MSG "WARNING: fan sensor out of range" -#define SKERR_I2C_E015 (SKERR_I2C_E014+1) -#define SKERR_I2C_E015MSG "ERROR: fan sensor out of range" -#define SKERR_I2C_E016 (SKERR_I2C_E015+1) -#define SKERR_I2C_E016MSG "TWSI: active transfer does not complete" - -/* - * Define Timeout values - */ -#define SK_I2C_TIM_LONG 2000000L /* 2 seconds */ -#define SK_I2C_TIM_SHORT 100000L /* 100 milliseconds */ -#define SK_I2C_TIM_WATCH 1000000L /* 1 second */ - -/* - * Define trap and error log hold times - */ -#ifndef SK_SEN_ERR_TR_HOLD -#define SK_SEN_ERR_TR_HOLD (4*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_ERR_LOG_HOLD -#define SK_SEN_ERR_LOG_HOLD (60*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_WARN_TR_HOLD -#define SK_SEN_WARN_TR_HOLD (15*SK_TICKS_PER_SEC) -#endif -#ifndef SK_SEN_WARN_LOG_HOLD -#define SK_SEN_WARN_LOG_HOLD (15*60*SK_TICKS_PER_SEC) -#endif - -/* - * Defines for SenType - */ -#define SK_SEN_UNKNOWN 0 -#define SK_SEN_TEMP 1 -#define SK_SEN_VOLT 2 -#define SK_SEN_FAN 3 - -/* - * Define for the SenErrorFlag - */ -#define SK_SEN_ERR_NOT_PRESENT 0 /* Error Flag: Sensor not present */ -#define SK_SEN_ERR_OK 1 /* Error Flag: O.K. */ -#define SK_SEN_ERR_WARN 2 /* Error Flag: Warning */ -#define SK_SEN_ERR_ERR 3 /* Error Flag: Error */ -#define SK_SEN_ERR_FAULTY 4 /* Error Flag: Faulty */ - -/* - * Define the Sensor struct - */ -struct s_Sensor { - char *SenDesc; /* Description */ - int SenType; /* Voltage or Temperature */ - SK_I32 SenValue; /* Current value of the sensor */ - SK_I32 SenThreErrHigh; /* High error Threshhold of this sensor */ - SK_I32 SenThreWarnHigh; /* High warning Threshhold of this sensor */ - SK_I32 SenThreErrLow; /* Lower error Threshold of the sensor */ - SK_I32 SenThreWarnLow; /* Lower warning Threshold of the sensor */ - int SenErrFlag; /* Sensor indicated an error */ - SK_BOOL SenInit; /* Is sensor initialized ? */ - SK_U64 SenErrCts; /* Error trap counter */ - SK_U64 SenWarnCts; /* Warning trap counter */ - SK_U64 SenBegErrTS; /* Begin error timestamp */ - SK_U64 SenBegWarnTS; /* Begin warning timestamp */ - SK_U64 SenLastErrTrapTS; /* Last error trap timestamp */ - SK_U64 SenLastErrLogTS; /* Last error log timestamp */ - SK_U64 SenLastWarnTrapTS; /* Last warning trap timestamp */ - SK_U64 SenLastWarnLogTS; /* Last warning log timestamp */ - int SenState; /* Sensor State (see HW specific include) */ - int (*SenRead)(SK_AC *pAC, SK_IOC IoC, struct s_Sensor *pSen); - /* Sensors read function */ - SK_U16 SenReg; /* Register Address for this sensor */ - SK_U8 SenDev; /* Device Selection for this sensor */ -}; - -typedef struct s_I2c { - SK_SENSOR SenTable[SK_MAX_SENSORS]; /* Sensor Table */ - int CurrSens; /* Which sensor is currently queried */ - int MaxSens; /* Max. number of sensors */ - int TimerMode; /* Use the timer also to watch the state machine */ - int InitLevel; /* Initialized Level */ -#ifndef SK_DIAG - int DummyReads; /* Number of non-checked dummy reads */ - SK_TIMER SenTimer; /* Sensors timer */ -#endif /* !SK_DIAG */ -} SK_I2C; - -extern int SkI2cInit(SK_AC *pAC, SK_IOC IoC, int Level); -#ifdef SK_DIAG -extern SK_U32 SkI2cRead(SK_AC *pAC, SK_IOC IoC, int Dev, int Size, int Reg, - int Burst); -#else /* !SK_DIAG */ -extern int SkI2cEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Para); -extern void SkI2cWaitIrq(SK_AC *pAC, SK_IOC IoC); -extern void SkI2cIsr(SK_AC *pAC, SK_IOC IoC); -#endif /* !SK_DIAG */ -#endif /* n_SKI2C_H */ - diff --git a/drivers/net/sk98lin/h/skqueue.h b/drivers/net/sk98lin/h/skqueue.h deleted file mode 100644 index 2ec40d4fdf60..000000000000 --- a/drivers/net/sk98lin/h/skqueue.h +++ /dev/null @@ -1,94 +0,0 @@ -/****************************************************************************** - * - * Name: skqueue.h - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.16 $ - * Date: $Date: 2003/09/16 12:50:32 $ - * Purpose: Defines for the Event queue - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKQUEUE.H contains all defines and types for the event queue - */ - -#ifndef _SKQUEUE_H_ -#define _SKQUEUE_H_ - - -/* - * define the event classes to be served - */ -#define SKGE_DRV 1 /* Driver Event Class */ -#define SKGE_RLMT 2 /* RLMT Event Class */ -#define SKGE_I2C 3 /* I2C Event Class */ -#define SKGE_PNMI 4 /* PNMI Event Class */ -#define SKGE_CSUM 5 /* Checksum Event Class */ -#define SKGE_HWAC 6 /* Hardware Access Event Class */ - -#define SKGE_SWT 9 /* Software Timer Event Class */ -#define SKGE_LACP 10 /* LACP Aggregation Event Class */ -#define SKGE_RSF 11 /* RSF Aggregation Event Class */ -#define SKGE_MARKER 12 /* MARKER Aggregation Event Class */ -#define SKGE_FD 13 /* FD Distributor Event Class */ - -/* - * define event queue as circular buffer - */ -#define SK_MAX_EVENT 64 - -/* - * Parameter union for the Para stuff - */ -typedef union u_EvPara { - void *pParaPtr; /* Parameter Pointer */ - SK_U64 Para64; /* Parameter 64bit version */ - SK_U32 Para32[2]; /* Parameter Array of 32bit parameters */ -} SK_EVPARA; - -/* - * Event Queue - * skqueue.c - * events are class/value pairs - * class is addressee, e.g. RLMT, PNMI etc. - * value is command, e.g. line state change, ring op change etc. - */ -typedef struct s_EventElem { - SK_U32 Class; /* Event class */ - SK_U32 Event; /* Event value */ - SK_EVPARA Para; /* Event parameter */ -} SK_EVENTELEM; - -typedef struct s_Queue { - SK_EVENTELEM EvQueue[SK_MAX_EVENT]; - SK_EVENTELEM *EvPut; - SK_EVENTELEM *EvGet; -} SK_QUEUE; - -extern void SkEventInit(SK_AC *pAC, SK_IOC Ioc, int Level); -extern void SkEventQueue(SK_AC *pAC, SK_U32 Class, SK_U32 Event, - SK_EVPARA Para); -extern int SkEventDispatcher(SK_AC *pAC, SK_IOC Ioc); - - -/* Define Error Numbers and messages */ -#define SKERR_Q_E001 (SK_ERRBASE_QUEUE+0) -#define SKERR_Q_E001MSG "Event queue overflow" -#define SKERR_Q_E002 (SKERR_Q_E001+1) -#define SKERR_Q_E002MSG "Undefined event class" -#endif /* _SKQUEUE_H_ */ - diff --git a/drivers/net/sk98lin/h/skrlmt.h b/drivers/net/sk98lin/h/skrlmt.h deleted file mode 100644 index ca75dfdcf2d6..000000000000 --- a/drivers/net/sk98lin/h/skrlmt.h +++ /dev/null @@ -1,438 +0,0 @@ -/****************************************************************************** - * - * Name: skrlmt.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.37 $ - * Date: $Date: 2003/04/15 09:43:43 $ - * Purpose: Header file for Redundant Link ManagemenT. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the header file for Redundant Link ManagemenT. - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * ... - * "sktypes.h" - * "skqueue.h" - * "skaddr.h" - * "skrlmt.h" - * ... - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef __INC_SKRLMT_H -#define __INC_SKRLMT_H - -#ifdef __cplusplus -extern "C" { -#endif /* cplusplus */ - -/* defines ********************************************************************/ - -#define SK_RLMT_NET_DOWN_TEMP 1 /* NET_DOWN due to last port down. */ -#define SK_RLMT_NET_DOWN_FINAL 2 /* NET_DOWN due to RLMT_STOP. */ - -/* ----- Default queue sizes - must be multiples of 8 KB ----- */ - -/* Less than 8 KB free in RX queue => pause frames. */ -#define SK_RLMT_STANDBY_QRXSIZE 128 /* Size of rx standby queue in KB. */ -#define SK_RLMT_STANDBY_QXASIZE 32 /* Size of async standby queue in KB. */ -#define SK_RLMT_STANDBY_QXSSIZE 0 /* Size of sync standby queue in KB. */ - -#define SK_RLMT_MAX_TX_BUF_SIZE 60 /* Maximum RLMT transmit size. */ - -/* ----- PORT states ----- */ - -#define SK_RLMT_PS_INIT 0 /* Port state: Init. */ -#define SK_RLMT_PS_LINK_DOWN 1 /* Port state: Link down. */ -#define SK_RLMT_PS_DOWN 2 /* Port state: Port down. */ -#define SK_RLMT_PS_GOING_UP 3 /* Port state: Going up. */ -#define SK_RLMT_PS_UP 4 /* Port state: Up. */ - -/* ----- RLMT states ----- */ - -#define SK_RLMT_RS_INIT 0 /* RLMT state: Init. */ -#define SK_RLMT_RS_NET_DOWN 1 /* RLMT state: Net down. */ -#define SK_RLMT_RS_NET_UP 2 /* RLMT state: Net up. */ - -/* ----- PORT events ----- */ - -#define SK_RLMT_LINK_UP 1001 /* Link came up. */ -#define SK_RLMT_LINK_DOWN 1002 /* Link went down. */ -#define SK_RLMT_PORT_ADDR 1003 /* Port address changed. */ - -/* ----- RLMT events ----- */ - -#define SK_RLMT_START 2001 /* Start RLMT. */ -#define SK_RLMT_STOP 2002 /* Stop RLMT. */ -#define SK_RLMT_PACKET_RECEIVED 2003 /* Packet was received for RLMT. */ -#define SK_RLMT_STATS_CLEAR 2004 /* Clear statistics. */ -#define SK_RLMT_STATS_UPDATE 2005 /* Update statistics. */ -#define SK_RLMT_PREFPORT_CHANGE 2006 /* Change preferred port. */ -#define SK_RLMT_MODE_CHANGE 2007 /* New RlmtMode. */ -#define SK_RLMT_SET_NETS 2008 /* Number of Nets (1 or 2). */ - -/* ----- RLMT mode bits ----- */ - -/* - * CAUTION: These defines are private to RLMT. - * Please use the RLMT mode defines below. - */ - -#define SK_RLMT_CHECK_LINK 1 /* Check Link. */ -#define SK_RLMT_CHECK_LOC_LINK 2 /* Check other link on same adapter. */ -#define SK_RLMT_CHECK_SEG 4 /* Check segmentation. */ - -#ifndef RLMT_CHECK_REMOTE -#define SK_RLMT_CHECK_OTHERS SK_RLMT_CHECK_LOC_LINK -#else /* RLMT_CHECK_REMOTE */ -#define SK_RLMT_CHECK_REM_LINK 8 /* Check link(s) on other adapter(s). */ -#define SK_RLMT_MAX_REMOTE_PORTS_CHECKED 3 -#define SK_RLMT_CHECK_OTHERS \ - (SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK) -#endif /* RLMT_CHECK_REMOTE */ - -#ifndef SK_RLMT_ENABLE_TRANSPARENT -#define SK_RLMT_TRANSPARENT 0 /* RLMT transparent - inactive. */ -#else /* SK_RLMT_ENABLE_TRANSPARENT */ -#define SK_RLMT_TRANSPARENT 128 /* RLMT transparent. */ -#endif /* SK_RLMT_ENABLE_TRANSPARENT */ - -/* ----- RLMT modes ----- */ - -/* Check Link State. */ -#define SK_RLMT_MODE_CLS (SK_RLMT_CHECK_LINK) - -/* Check Local Ports: check other links on the same adapter. */ -#define SK_RLMT_MODE_CLP (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK) - -/* Check Local Ports and Segmentation Status. */ -#define SK_RLMT_MODE_CLPSS \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_SEG) - -#ifdef RLMT_CHECK_REMOTE -/* Check Local and Remote Ports: check links (local or remote). */ - Name of define TBD! -#define SK_RLMT_MODE_CRP \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | SK_RLMT_CHECK_REM_LINK) - -/* Check Local and Remote Ports and Segmentation Status. */ - Name of define TBD! -#define SK_RLMT_MODE_CRPSS \ - (SK_RLMT_CHECK_LINK | SK_RLMT_CHECK_LOC_LINK | \ - SK_RLMT_CHECK_REM_LINK | SK_RLMT_CHECK_SEG) -#endif /* RLMT_CHECK_REMOTE */ - -/* ----- RLMT lookahead result bits ----- */ - -#define SK_RLMT_RX_RLMT 1 /* Give packet to RLMT. */ -#define SK_RLMT_RX_PROTOCOL 2 /* Give packet to protocol. */ - -/* Macros */ - -#if 0 -SK_AC *pAC /* adapter context */ -SK_U32 PortNum /* receiving port */ -unsigned PktLen /* received packet's length */ -SK_BOOL IsBc /* Flag: packet is broadcast */ -unsigned *pOffset /* offs. of bytes to present to SK_RLMT_LOOKAHEAD */ -unsigned *pNumBytes /* #Bytes to present to SK_RLMT_LOOKAHEAD */ -#endif /* 0 */ - -#define SK_RLMT_PRE_LOOKAHEAD(pAC,PortNum,PktLen,IsBc,pOffset,pNumBytes) { \ - SK_AC *_pAC; \ - SK_U32 _PortNum; \ - _pAC = (pAC); \ - _PortNum = (SK_U32)(PortNum); \ - /* _pAC->Rlmt.Port[_PortNum].PacketsRx++; */ \ - _pAC->Rlmt.Port[_PortNum].PacketsPerTimeSlot++; \ - if (_pAC->Rlmt.RlmtOff) { \ - *(pNumBytes) = 0; \ - } \ - else {\ - if ((_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_TRANSPARENT) != 0) { \ - *(pNumBytes) = 0; \ - } \ - else if (IsBc) { \ - if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode != SK_RLMT_MODE_CLS) { \ - *(pNumBytes) = 6; \ - *(pOffset) = 6; \ - } \ - else { \ - *(pNumBytes) = 0; \ - } \ - } \ - else { \ - if ((PktLen) > SK_RLMT_MAX_TX_BUF_SIZE) { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pNumBytes) = 0; \ - } \ - else { \ - *(pNumBytes) = 6; \ - *(pOffset) = 0; \ - } \ - } \ - } \ -} - -#if 0 -SK_AC *pAC /* adapter context */ -SK_U32 PortNum /* receiving port */ -SK_U8 *pLaPacket, /* received packet's data (points to pOffset) */ -SK_BOOL IsBc /* Flag: packet is broadcast */ -SK_BOOL IsMc /* Flag: packet is multicast */ -unsigned *pForRlmt /* Result: bits SK_RLMT_RX_RLMT, SK_RLMT_RX_PROTOCOL */ -SK_RLMT_LOOKAHEAD() expects *pNumBytes from -packet offset *pOffset (s.a.) at *pLaPacket. - -If you use SK_RLMT_LOOKAHEAD in a path where you already know if the packet is -BC, MC, or UC, you should use constants for IsBc and IsMc, so that your compiler -can trash unneeded parts of the if construction. -#endif /* 0 */ - -#define SK_RLMT_LOOKAHEAD(pAC,PortNum,pLaPacket,IsBc,IsMc,pForRlmt) { \ - SK_AC *_pAC; \ - SK_U32 _PortNum; \ - SK_U8 *_pLaPacket; \ - _pAC = (pAC); \ - _PortNum = (SK_U32)(PortNum); \ - _pLaPacket = (SK_U8 *)(pLaPacket); \ - if (IsBc) {\ - if (!SK_ADDR_EQUAL(_pLaPacket, _pAC->Addr.Net[_pAC->Rlmt.Port[ \ - _PortNum].Net->NetNumber].CurrentMacAddress.a)) { \ - _pAC->Rlmt.Port[_PortNum].BcTimeStamp = SkOsGetTime(_pAC); \ - _pAC->Rlmt.CheckSwitch = SK_TRUE; \ - } \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - else if (IsMc) { \ - if (SK_ADDR_EQUAL(_pLaPacket, BridgeMcAddr.a)) { \ - _pAC->Rlmt.Port[_PortNum].BpduPacketsPerTimeSlot++; \ - if (_pAC->Rlmt.Port[_PortNum].Net->RlmtMode & SK_RLMT_CHECK_SEG) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT | SK_RLMT_RX_PROTOCOL; \ - } \ - else { \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ - else if (SK_ADDR_EQUAL(_pLaPacket, SkRlmtMcAddr.a)) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT; \ - } \ - else { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ - else { \ - if (SK_ADDR_EQUAL( \ - _pLaPacket, \ - _pAC->Addr.Port[_PortNum].CurrentMacAddress.a)) { \ - *(pForRlmt) = SK_RLMT_RX_RLMT; \ - } \ - else { \ - /* _pAC->Rlmt.Port[_PortNum].DataPacketsPerTimeSlot++; */ \ - *(pForRlmt) = SK_RLMT_RX_PROTOCOL; \ - } \ - } \ -} - -#ifdef SK_RLMT_FAST_LOOKAHEAD -Error: SK_RLMT_FAST_LOOKAHEAD no longer used. Use new macros for lookahead. -#endif /* SK_RLMT_FAST_LOOKAHEAD */ -#ifdef SK_RLMT_SLOW_LOOKAHEAD -Error: SK_RLMT_SLOW_LOOKAHEAD no longer used. Use new macros for lookahead. -#endif /* SK_RLMT_SLOW_LOOKAHEAD */ - -/* typedefs *******************************************************************/ - -#ifdef SK_RLMT_MBUF_PRIVATE -typedef struct s_RlmtMbuf { - some content -} SK_RLMT_MBUF; -#endif /* SK_RLMT_MBUF_PRIVATE */ - - -#ifdef SK_LA_INFO -typedef struct s_Rlmt_PacketInfo { - unsigned PacketLength; /* Length of packet. */ - unsigned PacketType; /* Directed/Multicast/Broadcast. */ -} SK_RLMT_PINFO; -#endif /* SK_LA_INFO */ - - -typedef struct s_RootId { - SK_U8 Id[8]; /* Root Bridge Id. */ -} SK_RLMT_ROOT_ID; - - -typedef struct s_port { - SK_MAC_ADDR CheckAddr; - SK_BOOL SuspectTx; -} SK_PORT_CHECK; - - -typedef struct s_RlmtNet SK_RLMT_NET; - - -typedef struct s_RlmtPort { - -/* ----- Public part (read-only) ----- */ - - SK_U8 PortState; /* Current state of this port. */ - - /* For PNMI */ - SK_BOOL LinkDown; - SK_BOOL PortDown; - SK_U8 Align01; - - SK_U32 PortNumber; /* Number of port on adapter. */ - SK_RLMT_NET * Net; /* Net port belongs to. */ - - SK_U64 TxHelloCts; - SK_U64 RxHelloCts; - SK_U64 TxSpHelloReqCts; - SK_U64 RxSpHelloCts; - -/* ----- Private part ----- */ - -/* SK_U64 PacketsRx; */ /* Total packets received. */ - SK_U32 PacketsPerTimeSlot; /* Packets rxed between TOs. */ -/* SK_U32 DataPacketsPerTimeSlot; */ /* Data packets ... */ - SK_U32 BpduPacketsPerTimeSlot; /* BPDU packets rxed in TS. */ - SK_U64 BcTimeStamp; /* Time of last BC receive. */ - SK_U64 GuTimeStamp; /* Time of entering GOING_UP. */ - - SK_TIMER UpTimer; /* Timer struct Link/Port up. */ - SK_TIMER DownRxTimer; /* Timer struct down rx. */ - SK_TIMER DownTxTimer; /* Timer struct down tx. */ - - SK_U32 CheckingState; /* Checking State. */ - - SK_ADDR_PORT * AddrPort; - - SK_U8 Random[4]; /* Random value. */ - unsigned PortsChecked; /* #ports checked. */ - unsigned PortsSuspect; /* #ports checked that are s. */ - SK_PORT_CHECK PortCheck[1]; -/* SK_PORT_CHECK PortCheck[SK_MAX_MACS - 1]; */ - - SK_BOOL PortStarted; /* Port is started. */ - SK_BOOL PortNoRx; /* NoRx for >= 1 time slot. */ - SK_BOOL RootIdSet; - SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */ -} SK_RLMT_PORT; - - -struct s_RlmtNet { - -/* ----- Public part (read-only) ----- */ - - SK_U32 NetNumber; /* Number of net. */ - - SK_RLMT_PORT * Port[SK_MAX_MACS]; /* Ports that belong to this net. */ - SK_U32 NumPorts; /* Number of ports. */ - SK_U32 PrefPort; /* Preferred port. */ - - /* For PNMI */ - - SK_U32 ChgBcPrio; /* Change Priority of last broadcast received */ - SK_U32 RlmtMode; /* Check ... */ - SK_U32 ActivePort; /* Active port. */ - SK_U32 Preference; /* 0xFFFFFFFF: Automatic. */ - - SK_U8 RlmtState; /* Current RLMT state. */ - -/* ----- Private part ----- */ - SK_BOOL RootIdSet; - SK_U16 Align01; - - int LinksUp; /* #Links up. */ - int PortsUp; /* #Ports up. */ - SK_U32 TimeoutValue; /* RLMT timeout value. */ - - SK_U32 CheckingState; /* Checking State. */ - SK_RLMT_ROOT_ID Root; /* Root Bridge Id. */ - - SK_TIMER LocTimer; /* Timer struct. */ - SK_TIMER SegTimer; /* Timer struct. */ -}; - - -typedef struct s_Rlmt { - -/* ----- Public part (read-only) ----- */ - - SK_U32 NumNets; /* Number of nets. */ - SK_U32 NetsStarted; /* Number of nets started. */ - SK_RLMT_NET Net[SK_MAX_NETS]; /* Array of available nets. */ - SK_RLMT_PORT Port[SK_MAX_MACS]; /* Array of available ports. */ - -/* ----- Private part ----- */ - SK_BOOL CheckSwitch; - SK_BOOL RlmtOff; /* set to zero if the Mac addresses - are equal or the second one - is zero */ - SK_U16 Align01; - -} SK_RLMT; - - -extern SK_MAC_ADDR BridgeMcAddr; -extern SK_MAC_ADDR SkRlmtMcAddr; - -/* function prototypes ********************************************************/ - - -#ifndef SK_KR_PROTO - -/* Functions provided by SkRlmt */ - -/* ANSI/C++ compliant function prototypes */ - -extern void SkRlmtInit( - SK_AC *pAC, - SK_IOC IoC, - int Level); - -extern int SkRlmtEvent( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 Event, - SK_EVPARA Para); - -#else /* defined(SK_KR_PROTO) */ - -/* Non-ANSI/C++ compliant function prototypes */ - -#error KR-style function prototypes are not yet provided. - -#endif /* defined(SK_KR_PROTO)) */ - - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_SKRLMT_H */ diff --git a/drivers/net/sk98lin/h/sktimer.h b/drivers/net/sk98lin/h/sktimer.h deleted file mode 100644 index 04e6d7c1ec33..000000000000 --- a/drivers/net/sk98lin/h/sktimer.h +++ /dev/null @@ -1,63 +0,0 @@ -/****************************************************************************** - * - * Name: sktimer.h - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.11 $ - * Date: $Date: 2003/09/16 12:58:18 $ - * Purpose: Defines for the timer functions - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * SKTIMER.H contains all defines and types for the timer functions - */ - -#ifndef _SKTIMER_H_ -#define _SKTIMER_H_ - -#include "h/skqueue.h" - -/* - * SK timer - * - needed wherever a timer is used. Put this in your data structure - * wherever you want. - */ -typedef struct s_Timer SK_TIMER; - -struct s_Timer { - SK_TIMER *TmNext; /* linked list */ - SK_U32 TmClass; /* Timer Event class */ - SK_U32 TmEvent; /* Timer Event value */ - SK_EVPARA TmPara; /* Timer Event parameter */ - SK_U32 TmDelta; /* delta time */ - int TmActive; /* flag: active/inactive */ -}; - -/* - * Timer control struct. - * - use in Adapters context name pAC->Tim - */ -typedef struct s_TimCtrl { - SK_TIMER *StQueue; /* Head of Timer queue */ -} SK_TIMCTRL; - -extern void SkTimerInit(SK_AC *pAC, SK_IOC Ioc, int Level); -extern void SkTimerStop(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer); -extern void SkTimerStart(SK_AC *pAC, SK_IOC Ioc, SK_TIMER *pTimer, - SK_U32 Time, SK_U32 Class, SK_U32 Event, SK_EVPARA Para); -extern void SkTimerDone(SK_AC *pAC, SK_IOC Ioc); -#endif /* _SKTIMER_H_ */ diff --git a/drivers/net/sk98lin/h/sktypes.h b/drivers/net/sk98lin/h/sktypes.h deleted file mode 100644 index 40edc96e1055..000000000000 --- a/drivers/net/sk98lin/h/sktypes.h +++ /dev/null @@ -1,69 +0,0 @@ -/****************************************************************************** - * - * Name: sktypes.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.2 $ - * Date: $Date: 2003/10/07 08:16:51 $ - * Purpose: Define data types for Linux - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * In this file, all data types that are needed by the common modules - * are mapped to Linux data types. - * - * - * Include File Hierarchy: - * - * - ******************************************************************************/ - -#ifndef __INC_SKTYPES_H -#define __INC_SKTYPES_H - - -/* defines *******************************************************************/ - -/* - * Data types with a specific size. 'I' = signed, 'U' = unsigned. - */ -#define SK_I8 s8 -#define SK_U8 u8 -#define SK_I16 s16 -#define SK_U16 u16 -#define SK_I32 s32 -#define SK_U32 u32 -#define SK_I64 s64 -#define SK_U64 u64 - -#define SK_UPTR ulong /* casting pointer <-> integral */ - -/* -* Boolean type. -*/ -#define SK_BOOL SK_U8 -#define SK_FALSE 0 -#define SK_TRUE (!SK_FALSE) - -/* typedefs *******************************************************************/ - -/* function prototypes ********************************************************/ - -#endif /* __INC_SKTYPES_H */ diff --git a/drivers/net/sk98lin/h/skversion.h b/drivers/net/sk98lin/h/skversion.h deleted file mode 100644 index a1a7294828e5..000000000000 --- a/drivers/net/sk98lin/h/skversion.h +++ /dev/null @@ -1,38 +0,0 @@ -/****************************************************************************** - * - * Name: version.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 2003/10/07 08:16:51 $ - * Purpose: SK specific Error log support - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifdef lint -static const char SysKonnectFileId[] = "@(#) (C) SysKonnect GmbH."; -static const char SysKonnectBuildNumber[] = - "@(#)SK-BUILD: 6.23 PL: 01"; -#endif /* !defined(lint) */ - -#define BOOT_STRING "sk98lin: Network Device Driver v6.23\n" \ - "(C)Copyright 1999-2004 Marvell(R)." - -#define VER_STRING "6.23" -#define DRIVER_FILE_NAME "sk98lin" -#define DRIVER_REL_DATE "Feb-13-2004" - - diff --git a/drivers/net/sk98lin/h/skvpd.h b/drivers/net/sk98lin/h/skvpd.h deleted file mode 100644 index fdd9e48e8040..000000000000 --- a/drivers/net/sk98lin/h/skvpd.h +++ /dev/null @@ -1,248 +0,0 @@ -/****************************************************************************** - * - * Name: skvpd.h - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/01/13 10:39:38 $ - * Purpose: Defines and Macros for VPD handling - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * skvpd.h contains Diagnostic specific defines for VPD handling - */ - -#ifndef __INC_SKVPD_H_ -#define __INC_SKVPD_H_ - -/* - * Define Resource Type Identifiers and VPD keywords - */ -#define RES_ID 0x82 /* Resource Type ID String (Product Name) */ -#define RES_VPD_R 0x90 /* start of VPD read only area */ -#define RES_VPD_W 0x91 /* start of VPD read/write area */ -#define RES_END 0x78 /* Resource Type End Tag */ - -#ifndef VPD_NAME -#define VPD_NAME "Name" /* Product Name, VPD name of RES_ID */ -#endif /* VPD_NAME */ -#define VPD_PN "PN" /* Adapter Part Number */ -#define VPD_EC "EC" /* Adapter Engineering Level */ -#define VPD_MN "MN" /* Manufacture ID */ -#define VPD_SN "SN" /* Serial Number */ -#define VPD_CP "CP" /* Extended Capability */ -#define VPD_RV "RV" /* Checksum and Reserved */ -#define VPD_YA "YA" /* Asset Tag Identifier */ -#define VPD_VL "VL" /* First Error Log Message (SK specific) */ -#define VPD_VF "VF" /* Second Error Log Message (SK specific) */ -#define VPD_RW "RW" /* Remaining Read / Write Area */ - -/* 'type' values for vpd_setup_para() */ -#define VPD_RO_KEY 1 /* RO keys are "PN", "EC", "MN", "SN", "RV" */ -#define VPD_RW_KEY 2 /* RW keys are "Yx", "Vx", and "RW" */ - -/* 'op' values for vpd_setup_para() */ -#define ADD_KEY 1 /* add the key at the pos "RV" or "RW" */ -#define OWR_KEY 2 /* overwrite key if already exists */ - -/* - * Define READ and WRITE Constants. - */ - -#define VPD_DEV_ID_GENESIS 0x4300 - -#define VPD_SIZE_YUKON 256 -#define VPD_SIZE_GENESIS 512 -#define VPD_SIZE 512 -#define VPD_READ 0x0000 -#define VPD_WRITE 0x8000 - -#define VPD_STOP(pAC,IoC) VPD_OUT16(pAC,IoC,PCI_VPD_ADR_REG,VPD_WRITE) - -#define VPD_GET_RES_LEN(p) ((unsigned int) \ - (* (SK_U8 *)&(p)[1]) |\ - ((* (SK_U8 *)&(p)[2]) << 8)) -#define VPD_GET_VPD_LEN(p) ((unsigned int)(* (SK_U8 *)&(p)[2])) -#define VPD_GET_VAL(p) ((char *)&(p)[3]) - -#define VPD_MAX_LEN 50 - -/* VPD status */ - /* bit 7..1 reserved */ -#define VPD_VALID (1<<0) /* VPD data buffer, vpd_free_ro, */ - /* and vpd_free_rw valid */ - -/* - * VPD structs - */ -typedef struct s_vpd_status { - unsigned short Align01; /* Alignment */ - unsigned short vpd_status; /* VPD status, description see above */ - int vpd_free_ro; /* unused bytes in read only area */ - int vpd_free_rw; /* bytes available in read/write area */ -} SK_VPD_STATUS; - -typedef struct s_vpd { - SK_VPD_STATUS v; /* VPD status structure */ - char vpd_buf[VPD_SIZE]; /* VPD buffer */ - int rom_size; /* VPD ROM Size from PCI_OUR_REG_2 */ - int vpd_size; /* saved VPD-size */ -} SK_VPD; - -typedef struct s_vpd_para { - unsigned int p_len; /* parameter length */ - char *p_val; /* points to the value */ -} SK_VPD_PARA; - -/* - * structure of Large Resource Type Identifiers - */ - -/* was removed because of alignment problems */ - -/* - * structure of VPD keywords - */ -typedef struct s_vpd_key { - char p_key[2]; /* 2 bytes ID string */ - unsigned char p_len; /* 1 byte length */ - char p_val; /* start of the value string */ -} SK_VPD_KEY; - - -/* - * System specific VPD macros - */ -#ifndef SKDIAG -#ifndef VPD_DO_IO -#define VPD_OUT8(pAC,IoC,Addr,Val) (void)SkPciWriteCfgByte(pAC,Addr,Val) -#define VPD_OUT16(pAC,IoC,Addr,Val) (void)SkPciWriteCfgWord(pAC,Addr,Val) -#define VPD_IN8(pAC,IoC,Addr,pVal) (void)SkPciReadCfgByte(pAC,Addr,pVal) -#define VPD_IN16(pAC,IoC,Addr,pVal) (void)SkPciReadCfgWord(pAC,Addr,pVal) -#define VPD_IN32(pAC,IoC,Addr,pVal) (void)SkPciReadCfgDWord(pAC,Addr,pVal) -#else /* VPD_DO_IO */ -#define VPD_OUT8(pAC,IoC,Addr,Val) SK_OUT8(IoC,PCI_C(Addr),Val) -#define VPD_OUT16(pAC,IoC,Addr,Val) SK_OUT16(IoC,PCI_C(Addr),Val) -#define VPD_IN8(pAC,IoC,Addr,pVal) SK_IN8(IoC,PCI_C(Addr),pVal) -#define VPD_IN16(pAC,IoC,Addr,pVal) SK_IN16(IoC,PCI_C(Addr),pVal) -#define VPD_IN32(pAC,IoC,Addr,pVal) SK_IN32(IoC,PCI_C(Addr),pVal) -#endif /* VPD_DO_IO */ -#else /* SKDIAG */ -#define VPD_OUT8(pAC,Ioc,Addr,Val) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciWriteCfgByte(pAC,Addr,Val); \ - else \ - SK_OUT8(pAC,PCI_C(Addr),Val); \ - } -#define VPD_OUT16(pAC,Ioc,Addr,Val) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciWriteCfgWord(pAC,Addr,Val); \ - else \ - SK_OUT16(pAC,PCI_C(Addr),Val); \ - } -#define VPD_IN8(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgByte(pAC,Addr,pVal); \ - else \ - SK_IN8(pAC,PCI_C(Addr),pVal); \ - } -#define VPD_IN16(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgWord(pAC,Addr,pVal); \ - else \ - SK_IN16(pAC,PCI_C(Addr),pVal); \ - } -#define VPD_IN32(pAC,Ioc,Addr,pVal) { \ - if ((pAC)->DgT.DgUseCfgCycle) \ - SkPciReadCfgDWord(pAC,Addr,pVal); \ - else \ - SK_IN32(pAC,PCI_C(Addr),pVal); \ - } -#endif /* nSKDIAG */ - -/* function prototypes ********************************************************/ - -#ifndef SK_KR_PROTO -#ifdef SKDIAG -extern SK_U32 VpdReadDWord( - SK_AC *pAC, - SK_IOC IoC, - int addr); -#endif /* SKDIAG */ - -extern SK_VPD_STATUS *VpdStat( - SK_AC *pAC, - SK_IOC IoC); - -extern int VpdKeys( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int *len, - int *elements); - -extern int VpdRead( - SK_AC *pAC, - SK_IOC IoC, - const char *key, - char *buf, - int *len); - -extern SK_BOOL VpdMayWrite( - char *key); - -extern int VpdWrite( - SK_AC *pAC, - SK_IOC IoC, - const char *key, - const char *buf); - -extern int VpdDelete( - SK_AC *pAC, - SK_IOC IoC, - char *key); - -extern int VpdUpdate( - SK_AC *pAC, - SK_IOC IoC); - -#ifdef SKDIAG -extern int VpdReadBlock( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int addr, - int len); - -extern int VpdWriteBlock( - SK_AC *pAC, - SK_IOC IoC, - char *buf, - int addr, - int len); -#endif /* SKDIAG */ -#else /* SK_KR_PROTO */ -extern SK_U32 VpdReadDWord(); -extern SK_VPD_STATUS *VpdStat(); -extern int VpdKeys(); -extern int VpdRead(); -extern SK_BOOL VpdMayWrite(); -extern int VpdWrite(); -extern int VpdDelete(); -extern int VpdUpdate(); -#endif /* SK_KR_PROTO */ - -#endif /* __INC_SKVPD_H_ */ diff --git a/drivers/net/sk98lin/h/xmac_ii.h b/drivers/net/sk98lin/h/xmac_ii.h deleted file mode 100644 index 7f8e6d0084c7..000000000000 --- a/drivers/net/sk98lin/h/xmac_ii.h +++ /dev/null @@ -1,1579 +0,0 @@ -/****************************************************************************** - * - * Name: xmac_ii.h - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.52 $ - * Date: $Date: 2003/10/02 16:35:50 $ - * Purpose: Defines and Macros for Gigabit Ethernet Controller - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#ifndef __INC_XMAC_H -#define __INC_XMAC_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* defines ********************************************************************/ - -/* - * XMAC II registers - * - * The XMAC registers are 16 or 32 bits wide. - * The XMACs host processor interface is set to 16 bit mode, - * therefore ALL registers will be addressed with 16 bit accesses. - * - * The following macros are provided to access the XMAC registers - * XM_IN16(), XM_OUT16, XM_IN32(), XM_OUT32(), XM_INADR(), XM_OUTADR(), - * XM_INHASH(), and XM_OUTHASH(). - * The macros are defined in SkGeHw.h. - * - * Note: NA reg = Network Address e.g DA, SA etc. - * - */ -#define XM_MMU_CMD 0x0000 /* 16 bit r/w MMU Command Register */ - /* 0x0004: reserved */ -#define XM_POFF 0x0008 /* 32 bit r/w Packet Offset Register */ -#define XM_BURST 0x000c /* 32 bit r/w Burst Register for half duplex*/ -#define XM_1L_VLAN_TAG 0x0010 /* 16 bit r/w One Level VLAN Tag ID */ -#define XM_2L_VLAN_TAG 0x0014 /* 16 bit r/w Two Level VLAN Tag ID */ - /* 0x0018 - 0x001e: reserved */ -#define XM_TX_CMD 0x0020 /* 16 bit r/w Transmit Command Register */ -#define XM_TX_RT_LIM 0x0024 /* 16 bit r/w Transmit Retry Limit Register */ -#define XM_TX_STIME 0x0028 /* 16 bit r/w Transmit Slottime Register */ -#define XM_TX_IPG 0x002c /* 16 bit r/w Transmit Inter Packet Gap */ -#define XM_RX_CMD 0x0030 /* 16 bit r/w Receive Command Register */ -#define XM_PHY_ADDR 0x0034 /* 16 bit r/w PHY Address Register */ -#define XM_PHY_DATA 0x0038 /* 16 bit r/w PHY Data Register */ - /* 0x003c: reserved */ -#define XM_GP_PORT 0x0040 /* 32 bit r/w General Purpose Port Register */ -#define XM_IMSK 0x0044 /* 16 bit r/w Interrupt Mask Register */ -#define XM_ISRC 0x0048 /* 16 bit r/o Interrupt Status Register */ -#define XM_HW_CFG 0x004c /* 16 bit r/w Hardware Config Register */ - /* 0x0050 - 0x005e: reserved */ -#define XM_TX_LO_WM 0x0060 /* 16 bit r/w Tx FIFO Low Water Mark */ -#define XM_TX_HI_WM 0x0062 /* 16 bit r/w Tx FIFO High Water Mark */ -#define XM_TX_THR 0x0064 /* 16 bit r/w Tx Request Threshold */ -#define XM_HT_THR 0x0066 /* 16 bit r/w Host Request Threshold */ -#define XM_PAUSE_DA 0x0068 /* NA reg r/w Pause Destination Address */ - /* 0x006e: reserved */ -#define XM_CTL_PARA 0x0070 /* 32 bit r/w Control Parameter Register */ -#define XM_MAC_OPCODE 0x0074 /* 16 bit r/w Opcode for MAC control frames */ -#define XM_MAC_PTIME 0x0076 /* 16 bit r/w Pause time for MAC ctrl frames*/ -#define XM_TX_STAT 0x0078 /* 32 bit r/o Tx Status LIFO Register */ - - /* 0x0080 - 0x00fc: 16 NA reg r/w Exact Match Address Registers */ - /* use the XM_EXM() macro to address */ -#define XM_EXM_START 0x0080 /* r/w Start Address of the EXM Regs */ - - /* - * XM_EXM(Reg) - * - * returns the XMAC address offset of specified Exact Match Addr Reg - * - * para: Reg EXM register to addr (0 .. 15) - * - * usage: XM_INADDR(IoC, MAC_1, XM_EXM(i), &val[i]); - */ -#define XM_EXM(Reg) (XM_EXM_START + ((Reg) << 3)) - -#define XM_SRC_CHK 0x0100 /* NA reg r/w Source Check Address Register */ -#define XM_SA 0x0108 /* NA reg r/w Station Address Register */ -#define XM_HSM 0x0110 /* 64 bit r/w Hash Match Address Registers */ -#define XM_RX_LO_WM 0x0118 /* 16 bit r/w Receive Low Water Mark */ -#define XM_RX_HI_WM 0x011a /* 16 bit r/w Receive High Water Mark */ -#define XM_RX_THR 0x011c /* 32 bit r/w Receive Request Threshold */ -#define XM_DEV_ID 0x0120 /* 32 bit r/o Device ID Register */ -#define XM_MODE 0x0124 /* 32 bit r/w Mode Register */ -#define XM_LSA 0x0128 /* NA reg r/o Last Source Register */ - /* 0x012e: reserved */ -#define XM_TS_READ 0x0130 /* 32 bit r/o Time Stamp Read Register */ -#define XM_TS_LOAD 0x0134 /* 32 bit r/o Time Stamp Load Value */ - /* 0x0138 - 0x01fe: reserved */ -#define XM_STAT_CMD 0x0200 /* 16 bit r/w Statistics Command Register */ -#define XM_RX_CNT_EV 0x0204 /* 32 bit r/o Rx Counter Event Register */ -#define XM_TX_CNT_EV 0x0208 /* 32 bit r/o Tx Counter Event Register */ -#define XM_RX_EV_MSK 0x020c /* 32 bit r/w Rx Counter Event Mask */ -#define XM_TX_EV_MSK 0x0210 /* 32 bit r/w Tx Counter Event Mask */ - /* 0x0204 - 0x027e: reserved */ -#define XM_TXF_OK 0x0280 /* 32 bit r/o Frames Transmitted OK Conuter */ -#define XM_TXO_OK_HI 0x0284 /* 32 bit r/o Octets Transmitted OK High Cnt*/ -#define XM_TXO_OK_LO 0x0288 /* 32 bit r/o Octets Transmitted OK Low Cnt */ -#define XM_TXF_BC_OK 0x028c /* 32 bit r/o Broadcast Frames Xmitted OK */ -#define XM_TXF_MC_OK 0x0290 /* 32 bit r/o Multicast Frames Xmitted OK */ -#define XM_TXF_UC_OK 0x0294 /* 32 bit r/o Unicast Frames Xmitted OK */ -#define XM_TXF_LONG 0x0298 /* 32 bit r/o Tx Long Frame Counter */ -#define XM_TXE_BURST 0x029c /* 32 bit r/o Tx Burst Event Counter */ -#define XM_TXF_MPAUSE 0x02a0 /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */ -#define XM_TXF_MCTRL 0x02a4 /* 32 bit r/o Tx MAC Ctrl Frame Counter */ -#define XM_TXF_SNG_COL 0x02a8 /* 32 bit r/o Tx Single Collision Counter */ -#define XM_TXF_MUL_COL 0x02ac /* 32 bit r/o Tx Multiple Collision Counter */ -#define XM_TXF_ABO_COL 0x02b0 /* 32 bit r/o Tx aborted due to Exces. Col. */ -#define XM_TXF_LAT_COL 0x02b4 /* 32 bit r/o Tx Late Collision Counter */ -#define XM_TXF_DEF 0x02b8 /* 32 bit r/o Tx Deferred Frame Counter */ -#define XM_TXF_EX_DEF 0x02bc /* 32 bit r/o Tx Excessive Deferall Counter */ -#define XM_TXE_FIFO_UR 0x02c0 /* 32 bit r/o Tx FIFO Underrun Event Cnt */ -#define XM_TXE_CS_ERR 0x02c4 /* 32 bit r/o Tx Carrier Sense Error Cnt */ -#define XM_TXP_UTIL 0x02c8 /* 32 bit r/o Tx Utilization in % */ - /* 0x02cc - 0x02ce: reserved */ -#define XM_TXF_64B 0x02d0 /* 32 bit r/o 64 Byte Tx Frame Counter */ -#define XM_TXF_127B 0x02d4 /* 32 bit r/o 65-127 Byte Tx Frame Counter */ -#define XM_TXF_255B 0x02d8 /* 32 bit r/o 128-255 Byte Tx Frame Counter */ -#define XM_TXF_511B 0x02dc /* 32 bit r/o 256-511 Byte Tx Frame Counter */ -#define XM_TXF_1023B 0x02e0 /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/ -#define XM_TXF_MAX_SZ 0x02e4 /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/ - /* 0x02e8 - 0x02fe: reserved */ -#define XM_RXF_OK 0x0300 /* 32 bit r/o Frames Received OK */ -#define XM_RXO_OK_HI 0x0304 /* 32 bit r/o Octets Received OK High Cnt */ -#define XM_RXO_OK_LO 0x0308 /* 32 bit r/o Octets Received OK Low Counter*/ -#define XM_RXF_BC_OK 0x030c /* 32 bit r/o Broadcast Frames Received OK */ -#define XM_RXF_MC_OK 0x0310 /* 32 bit r/o Multicast Frames Received OK */ -#define XM_RXF_UC_OK 0x0314 /* 32 bit r/o Unicast Frames Received OK */ -#define XM_RXF_MPAUSE 0x0318 /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */ -#define XM_RXF_MCTRL 0x031c /* 32 bit r/o Rx MAC Ctrl Frame Counter */ -#define XM_RXF_INV_MP 0x0320 /* 32 bit r/o Rx invalid Pause Frame Cnt */ -#define XM_RXF_INV_MOC 0x0324 /* 32 bit r/o Rx Frames with inv. MAC Opcode*/ -#define XM_RXE_BURST 0x0328 /* 32 bit r/o Rx Burst Event Counter */ -#define XM_RXE_FMISS 0x032c /* 32 bit r/o Rx Missed Frames Event Cnt */ -#define XM_RXF_FRA_ERR 0x0330 /* 32 bit r/o Rx Framing Error Counter */ -#define XM_RXE_FIFO_OV 0x0334 /* 32 bit r/o Rx FIFO overflow Event Cnt */ -#define XM_RXF_JAB_PKT 0x0338 /* 32 bit r/o Rx Jabber Packet Frame Cnt */ -#define XM_RXE_CAR_ERR 0x033c /* 32 bit r/o Rx Carrier Event Error Cnt */ -#define XM_RXF_LEN_ERR 0x0340 /* 32 bit r/o Rx in Range Length Error */ -#define XM_RXE_SYM_ERR 0x0344 /* 32 bit r/o Rx Symbol Error Counter */ -#define XM_RXE_SHT_ERR 0x0348 /* 32 bit r/o Rx Short Event Error Cnt */ -#define XM_RXE_RUNT 0x034c /* 32 bit r/o Rx Runt Event Counter */ -#define XM_RXF_LNG_ERR 0x0350 /* 32 bit r/o Rx Frame too Long Error Cnt */ -#define XM_RXF_FCS_ERR 0x0354 /* 32 bit r/o Rx Frame Check Seq. Error Cnt */ - /* 0x0358 - 0x035a: reserved */ -#define XM_RXF_CEX_ERR 0x035c /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/ -#define XM_RXP_UTIL 0x0360 /* 32 bit r/o Rx Utilization in % */ - /* 0x0364 - 0x0366: reserved */ -#define XM_RXF_64B 0x0368 /* 32 bit r/o 64 Byte Rx Frame Counter */ -#define XM_RXF_127B 0x036c /* 32 bit r/o 65-127 Byte Rx Frame Counter */ -#define XM_RXF_255B 0x0370 /* 32 bit r/o 128-255 Byte Rx Frame Counter */ -#define XM_RXF_511B 0x0374 /* 32 bit r/o 256-511 Byte Rx Frame Counter */ -#define XM_RXF_1023B 0x0378 /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/ -#define XM_RXF_MAX_SZ 0x037c /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/ - /* 0x02e8 - 0x02fe: reserved */ - - -/*----------------------------------------------------------------------------*/ -/* - * XMAC Bit Definitions - * - * If the bit access behaviour differs from the register access behaviour - * (r/w, r/o) this is documented after the bit number. - * The following bit access behaviours are used: - * (sc) self clearing - * (ro) read only - */ - -/* XM_MMU_CMD 16 bit r/w MMU Command Register */ - /* Bit 15..13: reserved */ -#define XM_MMU_PHY_RDY (1<<12) /* Bit 12: PHY Read Ready */ -#define XM_MMU_PHY_BUSY (1<<11) /* Bit 11: PHY Busy */ -#define XM_MMU_IGN_PF (1<<10) /* Bit 10: Ignore Pause Frame */ -#define XM_MMU_MAC_LB (1<<9) /* Bit 9: Enable MAC Loopback */ - /* Bit 8: reserved */ -#define XM_MMU_FRC_COL (1<<7) /* Bit 7: Force Collision */ -#define XM_MMU_SIM_COL (1<<6) /* Bit 6: Simulate Collision */ -#define XM_MMU_NO_PRE (1<<5) /* Bit 5: No MDIO Preamble */ -#define XM_MMU_GMII_FD (1<<4) /* Bit 4: GMII uses Full Duplex */ -#define XM_MMU_RAT_CTRL (1<<3) /* Bit 3: Enable Rate Control */ -#define XM_MMU_GMII_LOOP (1<<2) /* Bit 2: PHY is in Loopback Mode */ -#define XM_MMU_ENA_RX (1<<1) /* Bit 1: Enable Receiver */ -#define XM_MMU_ENA_TX (1<<0) /* Bit 0: Enable Transmitter */ - - -/* XM_TX_CMD 16 bit r/w Transmit Command Register */ - /* Bit 15..7: reserved */ -#define XM_TX_BK2BK (1<<6) /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/ -#define XM_TX_ENC_BYP (1<<5) /* Bit 5: Set Encoder in Bypass Mode */ -#define XM_TX_SAM_LINE (1<<4) /* Bit 4: (sc) Start utilization calculation */ -#define XM_TX_NO_GIG_MD (1<<3) /* Bit 3: Disable Carrier Extension */ -#define XM_TX_NO_PRE (1<<2) /* Bit 2: Disable Preamble Generation */ -#define XM_TX_NO_CRC (1<<1) /* Bit 1: Disable CRC Generation */ -#define XM_TX_AUTO_PAD (1<<0) /* Bit 0: Enable Automatic Padding */ - - -/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */ - /* Bit 15..5: reserved */ -#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */ - - -/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */ - /* Bit 15..7: reserved */ -#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */ - - -/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */ - /* Bit 15..8: reserved */ -#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */ - - -/* XM_RX_CMD 16 bit r/w Receive Command Register */ - /* Bit 15..9: reserved */ -#define XM_RX_LENERR_OK (1<<8) /* Bit 8 don't set Rx Err bit for */ - /* inrange error packets */ -#define XM_RX_BIG_PK_OK (1<<7) /* Bit 7 don't set Rx Err bit for */ - /* jumbo packets */ -#define XM_RX_IPG_CAP (1<<6) /* Bit 6 repl. type field with IPG */ -#define XM_RX_TP_MD (1<<5) /* Bit 5: Enable transparent Mode */ -#define XM_RX_STRIP_FCS (1<<4) /* Bit 4: Enable FCS Stripping */ -#define XM_RX_SELF_RX (1<<3) /* Bit 3: Enable Rx of own packets */ -#define XM_RX_SAM_LINE (1<<2) /* Bit 2: (sc) Start utilization calculation */ -#define XM_RX_STRIP_PAD (1<<1) /* Bit 1: Strip pad bytes of Rx frames */ -#define XM_RX_DIS_CEXT (1<<0) /* Bit 0: Disable carrier ext. check */ - - -/* XM_PHY_ADDR 16 bit r/w PHY Address Register */ - /* Bit 15..5: reserved */ -#define XM_PHY_ADDR_SZ 0x1f /* Bit 4..0: PHY Address bits */ - - -/* XM_GP_PORT 32 bit r/w General Purpose Port Register */ - /* Bit 31..7: reserved */ -#define XM_GP_ANIP (1L<<6) /* Bit 6: (ro) Auto-Neg. in progress */ -#define XM_GP_FRC_INT (1L<<5) /* Bit 5: (sc) Force Interrupt */ - /* Bit 4: reserved */ -#define XM_GP_RES_MAC (1L<<3) /* Bit 3: (sc) Reset MAC and FIFOs */ -#define XM_GP_RES_STAT (1L<<2) /* Bit 2: (sc) Reset the statistics module */ - /* Bit 1: reserved */ -#define XM_GP_INP_ASS (1L<<0) /* Bit 0: (ro) GP Input Pin asserted */ - - -/* XM_IMSK 16 bit r/w Interrupt Mask Register */ -/* XM_ISRC 16 bit r/o Interrupt Status Register */ - /* Bit 15: reserved */ -#define XM_IS_LNK_AE (1<<14) /* Bit 14: Link Asynchronous Event */ -#define XM_IS_TX_ABORT (1<<13) /* Bit 13: Transmit Abort, late Col. etc */ -#define XM_IS_FRC_INT (1<<12) /* Bit 12: Force INT bit set in GP */ -#define XM_IS_INP_ASS (1<<11) /* Bit 11: Input Asserted, GP bit 0 set */ -#define XM_IS_LIPA_RC (1<<10) /* Bit 10: Link Partner requests config */ -#define XM_IS_RX_PAGE (1<<9) /* Bit 9: Page Received */ -#define XM_IS_TX_PAGE (1<<8) /* Bit 8: Next Page Loaded for Transmit */ -#define XM_IS_AND (1<<7) /* Bit 7: Auto-Negotiation Done */ -#define XM_IS_TSC_OV (1<<6) /* Bit 6: Time Stamp Counter Overflow */ -#define XM_IS_RXC_OV (1<<5) /* Bit 5: Rx Counter Event Overflow */ -#define XM_IS_TXC_OV (1<<4) /* Bit 4: Tx Counter Event Overflow */ -#define XM_IS_RXF_OV (1<<3) /* Bit 3: Receive FIFO Overflow */ -#define XM_IS_TXF_UR (1<<2) /* Bit 2: Transmit FIFO Underrun */ -#define XM_IS_TX_COMP (1<<1) /* Bit 1: Frame Tx Complete */ -#define XM_IS_RX_COMP (1<<0) /* Bit 0: Frame Rx Complete */ - -#define XM_DEF_MSK (~(XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE |\ - XM_IS_AND | XM_IS_RXC_OV | XM_IS_TXC_OV | XM_IS_TXF_UR)) - - -/* XM_HW_CFG 16 bit r/w Hardware Config Register */ - /* Bit 15.. 4: reserved */ -#define XM_HW_GEN_EOP (1<<3) /* Bit 3: generate End of Packet pulse */ -#define XM_HW_COM4SIG (1<<2) /* Bit 2: use Comma Detect for Sig. Det.*/ - /* Bit 1: reserved */ -#define XM_HW_GMII_MD (1<<0) /* Bit 0: GMII Interface selected */ - - -/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */ -/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */ - /* Bit 15..10 reserved */ -#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */ - -/* XM_TX_THR 16 bit r/w Tx Request Threshold */ -/* XM_HT_THR 16 bit r/w Host Request Threshold */ -/* XM_RX_THR 16 bit r/w Rx Request Threshold */ - /* Bit 15..11 reserved */ -#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */ - - -/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */ -#define XM_ST_VALID (1UL<<31) /* Bit 31: Status Valid */ -#define XM_ST_BYTE_CNT (0x3fffL<<17) /* Bit 30..17: Tx frame Length */ -#define XM_ST_RETRY_CNT (0x1fL<<12) /* Bit 16..12: Retry Count */ -#define XM_ST_EX_COL (1L<<11) /* Bit 11: Excessive Collisions */ -#define XM_ST_EX_DEF (1L<<10) /* Bit 10: Excessive Deferral */ -#define XM_ST_BURST (1L<<9) /* Bit 9: p. xmitted in burst md*/ -#define XM_ST_DEFER (1L<<8) /* Bit 8: packet was defered */ -#define XM_ST_BC (1L<<7) /* Bit 7: Broadcast packet */ -#define XM_ST_MC (1L<<6) /* Bit 6: Multicast packet */ -#define XM_ST_UC (1L<<5) /* Bit 5: Unicast packet */ -#define XM_ST_TX_UR (1L<<4) /* Bit 4: FIFO Underrun occured */ -#define XM_ST_CS_ERR (1L<<3) /* Bit 3: Carrier Sense Error */ -#define XM_ST_LAT_COL (1L<<2) /* Bit 2: Late Collision Error */ -#define XM_ST_MUL_COL (1L<<1) /* Bit 1: Multiple Collisions */ -#define XM_ST_SGN_COL (1L<<0) /* Bit 0: Single Collision */ - -/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */ -/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */ - /* Bit 15..11: reserved */ -#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */ - - -/* XM_DEV_ID 32 bit r/o Device ID Register */ -#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */ -#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */ - - -/* XM_MODE 32 bit r/w Mode Register */ - /* Bit 31..27: reserved */ -#define XM_MD_ENA_REJ (1L<<26) /* Bit 26: Enable Frame Reject */ -#define XM_MD_SPOE_E (1L<<25) /* Bit 25: Send Pause on Edge */ - /* extern generated */ -#define XM_MD_TX_REP (1L<<24) /* Bit 24: Transmit Repeater Mode */ -#define XM_MD_SPOFF_I (1L<<23) /* Bit 23: Send Pause on FIFO full */ - /* intern generated */ -#define XM_MD_LE_STW (1L<<22) /* Bit 22: Rx Stat Word in Little Endian */ -#define XM_MD_TX_CONT (1L<<21) /* Bit 21: Send Continuous */ -#define XM_MD_TX_PAUSE (1L<<20) /* Bit 20: (sc) Send Pause Frame */ -#define XM_MD_ATS (1L<<19) /* Bit 19: Append Time Stamp */ -#define XM_MD_SPOL_I (1L<<18) /* Bit 18: Send Pause on Low */ - /* intern generated */ -#define XM_MD_SPOH_I (1L<<17) /* Bit 17: Send Pause on High */ - /* intern generated */ -#define XM_MD_CAP (1L<<16) /* Bit 16: Check Address Pair */ -#define XM_MD_ENA_HASH (1L<<15) /* Bit 15: Enable Hashing */ -#define XM_MD_CSA (1L<<14) /* Bit 14: Check Station Address */ -#define XM_MD_CAA (1L<<13) /* Bit 13: Check Address Array */ -#define XM_MD_RX_MCTRL (1L<<12) /* Bit 12: Rx MAC Control Frame */ -#define XM_MD_RX_RUNT (1L<<11) /* Bit 11: Rx Runt Frames */ -#define XM_MD_RX_IRLE (1L<<10) /* Bit 10: Rx in Range Len Err Frame */ -#define XM_MD_RX_LONG (1L<<9) /* Bit 9: Rx Long Frame */ -#define XM_MD_RX_CRCE (1L<<8) /* Bit 8: Rx CRC Error Frame */ -#define XM_MD_RX_ERR (1L<<7) /* Bit 7: Rx Error Frame */ -#define XM_MD_DIS_UC (1L<<6) /* Bit 6: Disable Rx Unicast */ -#define XM_MD_DIS_MC (1L<<5) /* Bit 5: Disable Rx Multicast */ -#define XM_MD_DIS_BC (1L<<4) /* Bit 4: Disable Rx Broadcast */ -#define XM_MD_ENA_PROM (1L<<3) /* Bit 3: Enable Promiscuous */ -#define XM_MD_ENA_BE (1L<<2) /* Bit 2: Enable Big Endian */ -#define XM_MD_FTF (1L<<1) /* Bit 1: (sc) Flush Tx FIFO */ -#define XM_MD_FRF (1L<<0) /* Bit 0: (sc) Flush Rx FIFO */ - -#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I) -#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ - XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA | XM_MD_CAA) - -/* XM_STAT_CMD 16 bit r/w Statistics Command Register */ - /* Bit 16..6: reserved */ -#define XM_SC_SNP_RXC (1<<5) /* Bit 5: (sc) Snap Rx Counters */ -#define XM_SC_SNP_TXC (1<<4) /* Bit 4: (sc) Snap Tx Counters */ -#define XM_SC_CP_RXC (1<<3) /* Bit 3: Copy Rx Counters Continuously */ -#define XM_SC_CP_TXC (1<<2) /* Bit 2: Copy Tx Counters Continuously */ -#define XM_SC_CLR_RXC (1<<1) /* Bit 1: (sc) Clear Rx Counters */ -#define XM_SC_CLR_TXC (1<<0) /* Bit 0: (sc) Clear Tx Counters */ - - -/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */ -/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */ -#define XMR_MAX_SZ_OV (1UL<<31) /* Bit 31: 1024-MaxSize Rx Cnt Ov*/ -#define XMR_1023B_OV (1L<<30) /* Bit 30: 512-1023Byte Rx Cnt Ov*/ -#define XMR_511B_OV (1L<<29) /* Bit 29: 256-511 Byte Rx Cnt Ov*/ -#define XMR_255B_OV (1L<<28) /* Bit 28: 128-255 Byte Rx Cnt Ov*/ -#define XMR_127B_OV (1L<<27) /* Bit 27: 65-127 Byte Rx Cnt Ov */ -#define XMR_64B_OV (1L<<26) /* Bit 26: 64 Byte Rx Cnt Ov */ -#define XMR_UTIL_OV (1L<<25) /* Bit 25: Rx Util Cnt Overflow */ -#define XMR_UTIL_UR (1L<<24) /* Bit 24: Rx Util Cnt Underrun */ -#define XMR_CEX_ERR_OV (1L<<23) /* Bit 23: CEXT Err Cnt Ov */ - /* Bit 22: reserved */ -#define XMR_FCS_ERR_OV (1L<<21) /* Bit 21: Rx FCS Error Cnt Ov */ -#define XMR_LNG_ERR_OV (1L<<20) /* Bit 20: Rx too Long Err Cnt Ov*/ -#define XMR_RUNT_OV (1L<<19) /* Bit 19: Runt Event Cnt Ov */ -#define XMR_SHT_ERR_OV (1L<<18) /* Bit 18: Rx Short Ev Err Cnt Ov*/ -#define XMR_SYM_ERR_OV (1L<<17) /* Bit 17: Rx Sym Err Cnt Ov */ - /* Bit 16: reserved */ -#define XMR_CAR_ERR_OV (1L<<15) /* Bit 15: Rx Carr Ev Err Cnt Ov */ -#define XMR_JAB_PKT_OV (1L<<14) /* Bit 14: Rx Jabb Packet Cnt Ov */ -#define XMR_FIFO_OV (1L<<13) /* Bit 13: Rx FIFO Ov Ev Cnt Ov */ -#define XMR_FRA_ERR_OV (1L<<12) /* Bit 12: Rx Framing Err Cnt Ov */ -#define XMR_FMISS_OV (1L<<11) /* Bit 11: Rx Missed Ev Cnt Ov */ -#define XMR_BURST (1L<<10) /* Bit 10: Rx Burst Event Cnt Ov */ -#define XMR_INV_MOC (1L<<9) /* Bit 9: Rx with inv. MAC OC Ov*/ -#define XMR_INV_MP (1L<<8) /* Bit 8: Rx inv Pause Frame Ov */ -#define XMR_MCTRL_OV (1L<<7) /* Bit 7: Rx MAC Ctrl-F Cnt Ov */ -#define XMR_MPAUSE_OV (1L<<6) /* Bit 6: Rx Pause MAC Ctrl-F Ov*/ -#define XMR_UC_OK_OV (1L<<5) /* Bit 5: Rx Unicast Frame CntOv*/ -#define XMR_MC_OK_OV (1L<<4) /* Bit 4: Rx Multicast Cnt Ov */ -#define XMR_BC_OK_OV (1L<<3) /* Bit 3: Rx Broadcast Cnt Ov */ -#define XMR_OK_LO_OV (1L<<2) /* Bit 2: Octets Rx OK Low CntOv*/ -#define XMR_OK_HI_OV (1L<<1) /* Bit 1: Octets Rx OK Hi Cnt Ov*/ -#define XMR_OK_OV (1L<<0) /* Bit 0: Frames Received Ok Ov */ - -#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV) - -/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */ -/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */ - /* Bit 31..26: reserved */ -#define XMT_MAX_SZ_OV (1L<<25) /* Bit 25: 1024-MaxSize Tx Cnt Ov*/ -#define XMT_1023B_OV (1L<<24) /* Bit 24: 512-1023Byte Tx Cnt Ov*/ -#define XMT_511B_OV (1L<<23) /* Bit 23: 256-511 Byte Tx Cnt Ov*/ -#define XMT_255B_OV (1L<<22) /* Bit 22: 128-255 Byte Tx Cnt Ov*/ -#define XMT_127B_OV (1L<<21) /* Bit 21: 65-127 Byte Tx Cnt Ov */ -#define XMT_64B_OV (1L<<20) /* Bit 20: 64 Byte Tx Cnt Ov */ -#define XMT_UTIL_OV (1L<<19) /* Bit 19: Tx Util Cnt Overflow */ -#define XMT_UTIL_UR (1L<<18) /* Bit 18: Tx Util Cnt Underrun */ -#define XMT_CS_ERR_OV (1L<<17) /* Bit 17: Tx Carr Sen Err Cnt Ov*/ -#define XMT_FIFO_UR_OV (1L<<16) /* Bit 16: Tx FIFO Ur Ev Cnt Ov */ -#define XMT_EX_DEF_OV (1L<<15) /* Bit 15: Tx Ex Deferall Cnt Ov */ -#define XMT_DEF (1L<<14) /* Bit 14: Tx Deferred Cnt Ov */ -#define XMT_LAT_COL_OV (1L<<13) /* Bit 13: Tx Late Col Cnt Ov */ -#define XMT_ABO_COL_OV (1L<<12) /* Bit 12: Tx abo dueto Ex Col Ov*/ -#define XMT_MUL_COL_OV (1L<<11) /* Bit 11: Tx Mult Col Cnt Ov */ -#define XMT_SNG_COL (1L<<10) /* Bit 10: Tx Single Col Cnt Ov */ -#define XMT_MCTRL_OV (1L<<9) /* Bit 9: Tx MAC Ctrl Counter Ov*/ -#define XMT_MPAUSE (1L<<8) /* Bit 8: Tx Pause MAC Ctrl-F Ov*/ -#define XMT_BURST (1L<<7) /* Bit 7: Tx Burst Event Cnt Ov */ -#define XMT_LONG (1L<<6) /* Bit 6: Tx Long Frame Cnt Ov */ -#define XMT_UC_OK_OV (1L<<5) /* Bit 5: Tx Unicast Cnt Ov */ -#define XMT_MC_OK_OV (1L<<4) /* Bit 4: Tx Multicast Cnt Ov */ -#define XMT_BC_OK_OV (1L<<3) /* Bit 3: Tx Broadcast Cnt Ov */ -#define XMT_OK_LO_OV (1L<<2) /* Bit 2: Octets Tx OK Low CntOv*/ -#define XMT_OK_HI_OV (1L<<1) /* Bit 1: Octets Tx OK Hi Cnt Ov*/ -#define XMT_OK_OV (1L<<0) /* Bit 0: Frames Tx Ok Ov */ - -#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV) - -/* - * Receive Frame Status Encoding - */ -#define XMR_FS_LEN (0x3fffUL<<18) /* Bit 31..18: Rx Frame Length */ -#define XMR_FS_2L_VLAN (1L<<17) /* Bit 17: tagged wh 2Lev VLAN ID*/ -#define XMR_FS_1L_VLAN (1L<<16) /* Bit 16: tagged wh 1Lev VLAN ID*/ -#define XMR_FS_BC (1L<<15) /* Bit 15: Broadcast Frame */ -#define XMR_FS_MC (1L<<14) /* Bit 14: Multicast Frame */ -#define XMR_FS_UC (1L<<13) /* Bit 13: Unicast Frame */ - /* Bit 12: reserved */ -#define XMR_FS_BURST (1L<<11) /* Bit 11: Burst Mode */ -#define XMR_FS_CEX_ERR (1L<<10) /* Bit 10: Carrier Ext. Error */ -#define XMR_FS_802_3 (1L<<9) /* Bit 9: 802.3 Frame */ -#define XMR_FS_COL_ERR (1L<<8) /* Bit 8: Collision Error */ -#define XMR_FS_CAR_ERR (1L<<7) /* Bit 7: Carrier Event Error */ -#define XMR_FS_LEN_ERR (1L<<6) /* Bit 6: In-Range Length Error */ -#define XMR_FS_FRA_ERR (1L<<5) /* Bit 5: Framing Error */ -#define XMR_FS_RUNT (1L<<4) /* Bit 4: Runt Frame */ -#define XMR_FS_LNG_ERR (1L<<3) /* Bit 3: Giant (Jumbo) Frame */ -#define XMR_FS_FCS_ERR (1L<<2) /* Bit 2: Frame Check Sequ Err */ -#define XMR_FS_ERR (1L<<1) /* Bit 1: Frame Error */ -#define XMR_FS_MCTRL (1L<<0) /* Bit 0: MAC Control Packet */ - -/* - * XMR_FS_ERR will be set if - * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT, - * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR - * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue - * XMR_FS_ERR unless the corresponding bit in the Receive Command - * Register is set. - */ -#define XMR_FS_ANY_ERR XMR_FS_ERR - -/*----------------------------------------------------------------------------*/ -/* - * XMAC-PHY Registers, indirect addressed over the XMAC - */ -#define PHY_XMAC_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_XMAC_STAT 0x01 /* 16 bit r/w PHY Status Register */ -#define PHY_XMAC_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_XMAC_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_XMAC_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_XMAC_AUNE_LP 0x05 /* 16 bit r/o Link Partner Abi Reg */ -#define PHY_XMAC_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_XMAC_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_XMAC_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ - /* 0x09 - 0x0e: reserved */ -#define PHY_XMAC_EXT_STAT 0x0f /* 16 bit r/o Ext Status Register */ -#define PHY_XMAC_RES_ABI 0x10 /* 16 bit r/o PHY Resolved Ability */ - -/*----------------------------------------------------------------------------*/ -/* - * Broadcom-PHY Registers, indirect addressed over XMAC - */ -#define PHY_BCOM_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_BCOM_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_BCOM_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_BCOM_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_BCOM_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_BCOM_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_BCOM_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_BCOM_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_BCOM_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ - /* Broadcom-specific registers */ -#define PHY_BCOM_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ -#define PHY_BCOM_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b - 0x0e: reserved */ -#define PHY_BCOM_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_BCOM_P_EXT_CTRL 0x10 /* 16 bit r/w PHY Extended Ctrl Reg */ -#define PHY_BCOM_P_EXT_STAT 0x11 /* 16 bit r/o PHY Extended Stat Reg */ -#define PHY_BCOM_RE_CTR 0x12 /* 16 bit r/w Receive Error Counter */ -#define PHY_BCOM_FC_CTR 0x13 /* 16 bit r/w False Carrier Sense Cnt */ -#define PHY_BCOM_RNO_CTR 0x14 /* 16 bit r/w Receiver NOT_OK Cnt */ - /* 0x15 - 0x17: reserved */ -#define PHY_BCOM_AUX_CTRL 0x18 /* 16 bit r/w Auxiliary Control Reg */ -#define PHY_BCOM_AUX_STAT 0x19 /* 16 bit r/o Auxiliary Stat Summary */ -#define PHY_BCOM_INT_STAT 0x1a /* 16 bit r/o Interrupt Status Reg */ -#define PHY_BCOM_INT_MASK 0x1b /* 16 bit r/w Interrupt Mask Reg */ - /* 0x1c: reserved */ - /* 0x1d - 0x1f: test registers */ - -/*----------------------------------------------------------------------------*/ -/* - * Marvel-PHY Registers, indirect addressed over GMAC - */ -#define PHY_MARV_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_MARV_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_MARV_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_MARV_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_MARV_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_MARV_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_MARV_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_MARV_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_MARV_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ - /* Marvel-specific registers */ -#define PHY_MARV_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Ctrl Reg */ -#define PHY_MARV_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b - 0x0e: reserved */ -#define PHY_MARV_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_MARV_PHY_CTRL 0x10 /* 16 bit r/w PHY Specific Ctrl Reg */ -#define PHY_MARV_PHY_STAT 0x11 /* 16 bit r/o PHY Specific Stat Reg */ -#define PHY_MARV_INT_MASK 0x12 /* 16 bit r/w Interrupt Mask Reg */ -#define PHY_MARV_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ -#define PHY_MARV_EXT_CTRL 0x14 /* 16 bit r/w Ext. PHY Specific Ctrl */ -#define PHY_MARV_RXE_CNT 0x15 /* 16 bit r/w Receive Error Counter */ -#define PHY_MARV_EXT_ADR 0x16 /* 16 bit r/w Ext. Ad. for Cable Diag. */ - /* 0x17: reserved */ -#define PHY_MARV_LED_CTRL 0x18 /* 16 bit r/w LED Control Reg */ -#define PHY_MARV_LED_OVER 0x19 /* 16 bit r/w Manual LED Override Reg */ -#define PHY_MARV_EXT_CTRL_2 0x1a /* 16 bit r/w Ext. PHY Specific Ctrl 2 */ -#define PHY_MARV_EXT_P_STAT 0x1b /* 16 bit r/w Ext. PHY Spec. Stat Reg */ -#define PHY_MARV_CABLE_DIAG 0x1c /* 16 bit r/o Cable Diagnostic Reg */ - /* 0x1d - 0x1f: reserved */ - -/*----------------------------------------------------------------------------*/ -/* - * Level One-PHY Registers, indirect addressed over XMAC - */ -#define PHY_LONE_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_LONE_STAT 0x01 /* 16 bit r/o PHY Status Register */ -#define PHY_LONE_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_LONE_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_LONE_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_LONE_AUNE_LP 0x05 /* 16 bit r/o Link Part Ability Reg */ -#define PHY_LONE_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_LONE_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_LONE_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner */ - /* Level One-specific registers */ -#define PHY_LONE_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg*/ -#define PHY_LONE_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b -0x0e: reserved */ -#define PHY_LONE_EXT_STAT 0x0f /* 16 bit r/o Extended Status Reg */ -#define PHY_LONE_PORT_CFG 0x10 /* 16 bit r/w Port Configuration Reg*/ -#define PHY_LONE_Q_STAT 0x11 /* 16 bit r/o Quick Status Reg */ -#define PHY_LONE_INT_ENAB 0x12 /* 16 bit r/w Interrupt Enable Reg */ -#define PHY_LONE_INT_STAT 0x13 /* 16 bit r/o Interrupt Status Reg */ -#define PHY_LONE_LED_CFG 0x14 /* 16 bit r/w LED Configuration Reg */ -#define PHY_LONE_PORT_CTRL 0x15 /* 16 bit r/w Port Control Reg */ -#define PHY_LONE_CIM 0x16 /* 16 bit r/o CIM Reg */ - /* 0x17 -0x1c: reserved */ - -/*----------------------------------------------------------------------------*/ -/* - * National-PHY Registers, indirect addressed over XMAC - */ -#define PHY_NAT_CTRL 0x00 /* 16 bit r/w PHY Control Register */ -#define PHY_NAT_STAT 0x01 /* 16 bit r/w PHY Status Register */ -#define PHY_NAT_ID0 0x02 /* 16 bit r/o PHY ID0 Register */ -#define PHY_NAT_ID1 0x03 /* 16 bit r/o PHY ID1 Register */ -#define PHY_NAT_AUNE_ADV 0x04 /* 16 bit r/w Auto-Neg. Advertisement */ -#define PHY_NAT_AUNE_LP 0x05 /* 16 bit r/o Link Partner Ability Reg */ -#define PHY_NAT_AUNE_EXP 0x06 /* 16 bit r/o Auto-Neg. Expansion Reg */ -#define PHY_NAT_NEPG 0x07 /* 16 bit r/w Next Page Register */ -#define PHY_NAT_NEPG_LP 0x08 /* 16 bit r/o Next Page Link Partner Reg */ - /* National-specific registers */ -#define PHY_NAT_1000T_CTRL 0x09 /* 16 bit r/w 1000Base-T Control Reg */ -#define PHY_NAT_1000T_STAT 0x0a /* 16 bit r/o 1000Base-T Status Reg */ - /* 0x0b -0x0e: reserved */ -#define PHY_NAT_EXT_STAT 0x0f /* 16 bit r/o Extended Status Register */ -#define PHY_NAT_EXT_CTRL1 0x10 /* 16 bit r/o Extended Control Reg1 */ -#define PHY_NAT_Q_STAT1 0x11 /* 16 bit r/o Quick Status Reg1 */ -#define PHY_NAT_10B_OP 0x12 /* 16 bit r/o 10Base-T Operations Reg */ -#define PHY_NAT_EXT_CTRL2 0x13 /* 16 bit r/o Extended Control Reg1 */ -#define PHY_NAT_Q_STAT2 0x14 /* 16 bit r/o Quick Status Reg2 */ - /* 0x15 -0x18: reserved */ -#define PHY_NAT_PHY_ADDR 0x19 /* 16 bit r/o PHY Address Register */ - - -/*----------------------------------------------------------------------------*/ - -/* - * PHY bit definitions - * Bits defined as PHY_X_..., PHY_B_..., PHY_L_... or PHY_N_... are - * XMAC/Broadcom/LevelOne/National/Marvell-specific. - * All other are general. - */ - -/***** PHY_XMAC_CTRL 16 bit r/w PHY Control Register *****/ -/***** PHY_BCOM_CTRL 16 bit r/w PHY Control Register *****/ -/***** PHY_MARV_CTRL 16 bit r/w PHY Status Register *****/ -/***** PHY_LONE_CTRL 16 bit r/w PHY Control Register *****/ -#define PHY_CT_RESET (1<<15) /* Bit 15: (sc) clear all PHY related regs */ -#define PHY_CT_LOOP (1<<14) /* Bit 14: enable Loopback over PHY */ -#define PHY_CT_SPS_LSB (1<<13) /* Bit 13: (BC,L1) Speed select, lower bit */ -#define PHY_CT_ANE (1<<12) /* Bit 12: Auto-Negotiation Enabled */ -#define PHY_CT_PDOWN (1<<11) /* Bit 11: (BC,L1) Power Down Mode */ -#define PHY_CT_ISOL (1<<10) /* Bit 10: (BC,L1) Isolate Mode */ -#define PHY_CT_RE_CFG (1<<9) /* Bit 9: (sc) Restart Auto-Negotiation */ -#define PHY_CT_DUP_MD (1<<8) /* Bit 8: Duplex Mode */ -#define PHY_CT_COL_TST (1<<7) /* Bit 7: (BC,L1) Collision Test enabled */ -#define PHY_CT_SPS_MSB (1<<6) /* Bit 6: (BC,L1) Speed select, upper bit */ - /* Bit 5..0: reserved */ - -#define PHY_CT_SP1000 PHY_CT_SPS_MSB /* enable speed of 1000 Mbps */ -#define PHY_CT_SP100 PHY_CT_SPS_LSB /* enable speed of 100 Mbps */ -#define PHY_CT_SP10 (0) /* enable speed of 10 Mbps */ - - -/***** PHY_XMAC_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_BCOM_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_MARV_STAT 16 bit r/w PHY Status Register *****/ -/***** PHY_LONE_STAT 16 bit r/w PHY Status Register *****/ - /* Bit 15..9: reserved */ - /* (BC/L1) 100/10 Mbps cap bits ignored*/ -#define PHY_ST_EXT_ST (1<<8) /* Bit 8: Extended Status Present */ - /* Bit 7: reserved */ -#define PHY_ST_PRE_SUP (1<<6) /* Bit 6: (BC/L1) preamble suppression */ -#define PHY_ST_AN_OVER (1<<5) /* Bit 5: Auto-Negotiation Over */ -#define PHY_ST_REM_FLT (1<<4) /* Bit 4: Remote Fault Condition Occured */ -#define PHY_ST_AN_CAP (1<<3) /* Bit 3: Auto-Negotiation Capability */ -#define PHY_ST_LSYNC (1<<2) /* Bit 2: Link Synchronized */ -#define PHY_ST_JAB_DET (1<<1) /* Bit 1: (BC/L1) Jabber Detected */ -#define PHY_ST_EXT_REG (1<<0) /* Bit 0: Extended Register available */ - - -/***** PHY_XMAC_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_BCOM_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_MARV_ID1 16 bit r/o PHY ID1 Register */ -/***** PHY_LONE_ID1 16 bit r/o PHY ID1 Register */ -#define PHY_I1_OUI_MSK (0x3f<<10) /* Bit 15..10: Organization Unique ID */ -#define PHY_I1_MOD_NUM (0x3f<<4) /* Bit 9.. 4: Model Number */ -#define PHY_I1_REV_MSK 0x0f /* Bit 3.. 0: Revision Number */ - -/* different Broadcom PHY Ids */ -#define PHY_BCOM_ID1_A1 0x6041 -#define PHY_BCOM_ID1_B2 0x6043 -#define PHY_BCOM_ID1_C0 0x6044 -#define PHY_BCOM_ID1_C5 0x6047 - - -/***** PHY_XMAC_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_XMAC_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -#define PHY_AN_NXT_PG (1<<15) /* Bit 15: Request Next Page */ -#define PHY_X_AN_ACK (1<<14) /* Bit 14: (ro) Acknowledge Received */ -#define PHY_X_AN_RFB (3<<12) /* Bit 13..12: Remote Fault Bits */ - /* Bit 11.. 9: reserved */ -#define PHY_X_AN_PAUSE (3<<7) /* Bit 8.. 7: Pause Bits */ -#define PHY_X_AN_HD (1<<6) /* Bit 6: Half Duplex */ -#define PHY_X_AN_FD (1<<5) /* Bit 5: Full Duplex */ - /* Bit 4.. 0: reserved */ - -/***** PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_B_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_B_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */ -#define PHY_B_AN_PC (1<<10) /* Bit 10: Pause Capable */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_B_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/***** PHY_LONE_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_LONE_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_L_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_L_AN_ASP (1<<11) /* Bit 11: Asymmetric Pause */ -#define PHY_L_AN_PC (1<<10) /* Bit 10: Pause Capable */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_L_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/***** PHY_NAT_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_NAT_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -/* PHY_AN_NXT_PG (see XMAC) Bit 15: Request Next Page */ - /* Bit 14: reserved */ -#define PHY_N_AN_RF (1<<13) /* Bit 13: Remote Fault */ - /* Bit 12: reserved */ -#define PHY_N_AN_100F (1<<11) /* Bit 11: 100Base-T2 FD Support */ -#define PHY_N_AN_100H (1<<10) /* Bit 10: 100Base-T2 HD Support */ - /* Bit 9..5: 100/10 BT cap bits ingnored */ -#define PHY_N_AN_SEL 0x1f /* Bit 4..0: Selector Field, 00001=Ethernet*/ - -/* field type definition for PHY_x_AN_SEL */ -#define PHY_SEL_TYPE 0x01 /* 00001 = Ethernet */ - -/***** PHY_XMAC_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ - /* Bit 15..4: reserved */ -#define PHY_ANE_LP_NP (1<<3) /* Bit 3: Link Partner can Next Page */ -#define PHY_ANE_LOC_NP (1<<2) /* Bit 2: Local PHY can Next Page */ -#define PHY_ANE_RX_PG (1<<1) /* Bit 1: Page Received */ - /* Bit 0: reserved */ - -/***** PHY_BCOM_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ -/***** PHY_LONE_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ -/***** PHY_MARV_AUNE_EXP 16 bit r/o Auto-Negotiation Expansion Reg *****/ - /* Bit 15..5: reserved */ -#define PHY_ANE_PAR_DF (1<<4) /* Bit 4: Parallel Detection Fault */ -/* PHY_ANE_LP_NP (see XMAC) Bit 3: Link Partner can Next Page */ -/* PHY_ANE_LOC_NP (see XMAC) Bit 2: Local PHY can Next Page */ -/* PHY_ANE_RX_PG (see XMAC) Bit 1: Page Received */ -#define PHY_ANE_LP_CAP (1<<0) /* Bit 0: Link Partner Auto-Neg. Cap. */ - -/***** PHY_XMAC_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_BCOM_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_LONE_NEPG 16 bit r/w Next Page Register *****/ -/***** PHY_XMAC_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -/***** PHY_BCOM_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -/***** PHY_LONE_NEPG_LP 16 bit r/o Next Page Link Partner *****/ -#define PHY_NP_MORE (1<<15) /* Bit 15: More, Next Pages to follow */ -#define PHY_NP_ACK1 (1<<14) /* Bit 14: (ro) Ack1, for receiving a message */ -#define PHY_NP_MSG_VAL (1<<13) /* Bit 13: Message Page valid */ -#define PHY_NP_ACK2 (1<<12) /* Bit 12: Ack2, comply with msg content */ -#define PHY_NP_TOG (1<<11) /* Bit 11: Toggle Bit, ensure sync */ -#define PHY_NP_MSG 0x07ff /* Bit 10..0: Message from/to Link Partner */ - -/* - * XMAC-Specific - */ -/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/ -#define PHY_X_EX_FD (1<<15) /* Bit 15: Device Supports Full Duplex */ -#define PHY_X_EX_HD (1<<14) /* Bit 14: Device Supports Half Duplex */ - /* Bit 13..0: reserved */ - -/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/ - /* Bit 15..9: reserved */ -#define PHY_X_RS_PAUSE (3<<7) /* Bit 8..7: selected Pause Mode */ -#define PHY_X_RS_HD (1<<6) /* Bit 6: Half Duplex Mode selected */ -#define PHY_X_RS_FD (1<<5) /* Bit 5: Full Duplex Mode selected */ -#define PHY_X_RS_ABLMIS (1<<4) /* Bit 4: duplex or pause cap mismatch */ -#define PHY_X_RS_PAUMIS (1<<3) /* Bit 3: pause capability mismatch */ - /* Bit 2..0: reserved */ -/* - * Remote Fault Bits (PHY_X_AN_RFB) encoding - */ -#define X_RFB_OK (0<<12) /* Bit 13..12 No errors, Link OK */ -#define X_RFB_LF (1<<12) /* Bit 13..12 Link Failure */ -#define X_RFB_OFF (2<<12) /* Bit 13..12 Offline */ -#define X_RFB_AN_ERR (3<<12) /* Bit 13..12 Auto-Negotiation Error */ - -/* - * Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding - */ -#define PHY_X_P_NO_PAUSE (0<<7) /* Bit 8..7: no Pause Mode */ -#define PHY_X_P_SYM_MD (1<<7) /* Bit 8..7: symmetric Pause Mode */ -#define PHY_X_P_ASYM_MD (2<<7) /* Bit 8..7: asymmetric Pause Mode */ -#define PHY_X_P_BOTH_MD (3<<7) /* Bit 8..7: both Pause Mode */ - - -/* - * Broadcom-Specific - */ -/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_B_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_B_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_B_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_B_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_B_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_B_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_B_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_B_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_B_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_B_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */ -#define PHY_B_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_B_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ - /* Bit 9..8: reserved */ -#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_B_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_B_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_B_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_B_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/ -#define PHY_B_PEC_MAC_PHY (1<<15) /* Bit 15: 10BIT/GMI-Interface */ -#define PHY_B_PEC_DIS_CROSS (1<<14) /* Bit 14: Disable MDI Crossover */ -#define PHY_B_PEC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */ -#define PHY_B_PEC_INT_DIS (1<<12) /* Bit 12: Interrupts Disabled */ -#define PHY_B_PEC_F_INT (1<<11) /* Bit 11: Force Interrupt */ -#define PHY_B_PEC_BY_45 (1<<10) /* Bit 10: Bypass 4B5B-Decoder */ -#define PHY_B_PEC_BY_SCR (1<<9) /* Bit 9: Bypass Scrambler */ -#define PHY_B_PEC_BY_MLT3 (1<<8) /* Bit 8: Bypass MLT3 Encoder */ -#define PHY_B_PEC_BY_RXA (1<<7) /* Bit 7: Bypass Rx Alignm. */ -#define PHY_B_PEC_RES_SCR (1<<6) /* Bit 6: Reset Scrambler */ -#define PHY_B_PEC_EN_LTR (1<<5) /* Bit 5: Ena LED Traffic Mode */ -#define PHY_B_PEC_LED_ON (1<<4) /* Bit 4: Force LED's on */ -#define PHY_B_PEC_LED_OFF (1<<3) /* Bit 3: Force LED's off */ -#define PHY_B_PEC_EX_IPG (1<<2) /* Bit 2: Extend Tx IPG Mode */ -#define PHY_B_PEC_3_LED (1<<1) /* Bit 1: Three Link LED mode */ -#define PHY_B_PEC_HIGH_LA (1<<0) /* Bit 0: GMII FIFO Elasticy */ - -/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/ - /* Bit 15..14: reserved */ -#define PHY_B_PES_CROSS_STAT (1<<13) /* Bit 13: MDI Crossover Status */ -#define PHY_B_PES_INT_STAT (1<<12) /* Bit 12: Interrupt Status */ -#define PHY_B_PES_RRS (1<<11) /* Bit 11: Remote Receiver Stat. */ -#define PHY_B_PES_LRS (1<<10) /* Bit 10: Local Receiver Stat. */ -#define PHY_B_PES_LOCKED (1<<9) /* Bit 9: Locked */ -#define PHY_B_PES_LS (1<<8) /* Bit 8: Link Status */ -#define PHY_B_PES_RF (1<<7) /* Bit 7: Remote Fault */ -#define PHY_B_PES_CE_ER (1<<6) /* Bit 6: Carrier Ext Error */ -#define PHY_B_PES_BAD_SSD (1<<5) /* Bit 5: Bad SSD */ -#define PHY_B_PES_BAD_ESD (1<<4) /* Bit 4: Bad ESD */ -#define PHY_B_PES_RX_ER (1<<3) /* Bit 3: Receive Error */ -#define PHY_B_PES_TX_ER (1<<2) /* Bit 2: Transmit Error */ -#define PHY_B_PES_LOCK_ER (1<<1) /* Bit 1: Lock Error */ -#define PHY_B_PES_MLT3_ER (1<<0) /* Bit 0: MLT3 code Error */ - -/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ - /* Bit 15..8: reserved */ -#define PHY_B_FC_CTR 0xff /* Bit 7..0: False Carrier Counter */ - -/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/ -#define PHY_B_RC_LOC_MSK 0xff00 /* Bit 15..8: Local Rx NOT_OK cnt */ -#define PHY_B_RC_REM_MSK 0x00ff /* Bit 7..0: Remote Rx NOT_OK cnt */ - -/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/ -#define PHY_B_AC_L_SQE (1<<15) /* Bit 15: Low Squelch */ -#define PHY_B_AC_LONG_PACK (1<<14) /* Bit 14: Rx Long Packets */ -#define PHY_B_AC_ER_CTRL (3<<12) /* Bit 13..12: Edgerate Control */ - /* Bit 11: reserved */ -#define PHY_B_AC_TX_TST (1<<10) /* Bit 10: Tx test bit, always 1 */ - /* Bit 9.. 8: reserved */ -#define PHY_B_AC_DIS_PRF (1<<7) /* Bit 7: dis part resp filter */ - /* Bit 6: reserved */ -#define PHY_B_AC_DIS_PM (1<<5) /* Bit 5: dis power management */ - /* Bit 4: reserved */ -#define PHY_B_AC_DIAG (1<<3) /* Bit 3: Diagnostic Mode */ - /* Bit 2.. 0: reserved */ - -/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/ -#define PHY_B_AS_AN_C (1<<15) /* Bit 15: AutoNeg complete */ -#define PHY_B_AS_AN_CA (1<<14) /* Bit 14: AN Complete Ack */ -#define PHY_B_AS_ANACK_D (1<<13) /* Bit 13: AN Ack Detect */ -#define PHY_B_AS_ANAB_D (1<<12) /* Bit 12: AN Ability Detect */ -#define PHY_B_AS_NPW (1<<11) /* Bit 11: AN Next Page Wait */ -#define PHY_B_AS_AN_RES_MSK (7<<8) /* Bit 10..8: AN HDC */ -#define PHY_B_AS_PDF (1<<7) /* Bit 7: Parallel Detect. Fault */ -#define PHY_B_AS_RF (1<<6) /* Bit 6: Remote Fault */ -#define PHY_B_AS_ANP_R (1<<5) /* Bit 5: AN Page Received */ -#define PHY_B_AS_LP_ANAB (1<<4) /* Bit 4: LP AN Ability */ -#define PHY_B_AS_LP_NPAB (1<<3) /* Bit 3: LP Next Page Ability */ -#define PHY_B_AS_LS (1<<2) /* Bit 2: Link Status */ -#define PHY_B_AS_PRR (1<<1) /* Bit 1: Pause Resolution-Rx */ -#define PHY_B_AS_PRT (1<<0) /* Bit 0: Pause Resolution-Tx */ - -#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT) - -/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ - /* Bit 15: reserved */ -#define PHY_B_IS_PSE (1<<14) /* Bit 14: Pair Swap Error */ -#define PHY_B_IS_MDXI_SC (1<<13) /* Bit 13: MDIX Status Change */ -#define PHY_B_IS_HCT (1<<12) /* Bit 12: counter above 32k */ -#define PHY_B_IS_LCT (1<<11) /* Bit 11: counter above 128 */ -#define PHY_B_IS_AN_PR (1<<10) /* Bit 10: Page Received */ -#define PHY_B_IS_NO_HDCL (1<<9) /* Bit 9: No HCD Link */ -#define PHY_B_IS_NO_HDC (1<<8) /* Bit 8: No HCD */ -#define PHY_B_IS_NEG_USHDC (1<<7) /* Bit 7: Negotiated Unsup. HCD */ -#define PHY_B_IS_SCR_S_ER (1<<6) /* Bit 6: Scrambler Sync Error */ -#define PHY_B_IS_RRS_CHANGE (1<<5) /* Bit 5: Remote Rx Stat Change */ -#define PHY_B_IS_LRS_CHANGE (1<<4) /* Bit 4: Local Rx Stat Change */ -#define PHY_B_IS_DUP_CHANGE (1<<3) /* Bit 3: Duplex Mode Change */ -#define PHY_B_IS_LSP_CHANGE (1<<2) /* Bit 2: Link Speed Change */ -#define PHY_B_IS_LST_CHANGE (1<<1) /* Bit 1: Link Status Changed */ -#define PHY_B_IS_CRC_ER (1<<0) /* Bit 0: CRC Error */ - -#define PHY_B_DEF_MSK (~(PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) - -/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ -#define PHY_B_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */ -#define PHY_B_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */ -#define PHY_B_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ -#define PHY_B_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ - -/* - * Resolved Duplex mode and Capabilities (Aux Status Summary Reg) - */ -#define PHY_B_RES_1000FD (7<<8) /* Bit 10..8: 1000Base-T Full Dup. */ -#define PHY_B_RES_1000HD (6<<8) /* Bit 10..8: 1000Base-T Half Dup. */ -/* others: 100/10: invalid for us */ - -/* - * Level One-Specific - */ -/***** PHY_LONE_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_L_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_L_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_L_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_L_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_L_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_L_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_LONE_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_L_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_L_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_L_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_L_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status */ -#define PHY_L_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_L_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ - /* Bit 9..8: reserved */ -#define PHY_B_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_LONE_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_L_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_L_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_L_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_L_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/***** PHY_LONE_PORT_CFG 16 bit r/w Port Configuration Reg *****/ -#define PHY_L_PC_REP_MODE (1<<15) /* Bit 15: Repeater Mode */ - /* Bit 14: reserved */ -#define PHY_L_PC_TX_DIS (1<<13) /* Bit 13: Tx output Disabled */ -#define PHY_L_PC_BY_SCR (1<<12) /* Bit 12: Bypass Scrambler */ -#define PHY_L_PC_BY_45 (1<<11) /* Bit 11: Bypass 4B5B-Decoder */ -#define PHY_L_PC_JAB_DIS (1<<10) /* Bit 10: Jabber Disabled */ -#define PHY_L_PC_SQE (1<<9) /* Bit 9: Enable Heartbeat */ -#define PHY_L_PC_TP_LOOP (1<<8) /* Bit 8: TP Loopback */ -#define PHY_L_PC_SSS (1<<7) /* Bit 7: Smart Speed Selection */ -#define PHY_L_PC_FIFO_SIZE (1<<6) /* Bit 6: FIFO Size */ -#define PHY_L_PC_PRE_EN (1<<5) /* Bit 5: Preamble Enable */ -#define PHY_L_PC_CIM (1<<4) /* Bit 4: Carrier Integrity Mon */ -#define PHY_L_PC_10_SER (1<<3) /* Bit 3: Use Serial Output */ -#define PHY_L_PC_ANISOL (1<<2) /* Bit 2: Unisolate Port */ -#define PHY_L_PC_TEN_BIT (1<<1) /* Bit 1: 10bit iface mode on */ -#define PHY_L_PC_ALTCLOCK (1<<0) /* Bit 0: (ro) ALTCLOCK Mode on */ - -/***** PHY_LONE_Q_STAT 16 bit r/o Quick Status Reg *****/ -#define PHY_L_QS_D_RATE (3<<14) /* Bit 15..14: Data Rate */ -#define PHY_L_QS_TX_STAT (1<<13) /* Bit 13: Transmitting */ -#define PHY_L_QS_RX_STAT (1<<12) /* Bit 12: Receiving */ -#define PHY_L_QS_COL_STAT (1<<11) /* Bit 11: Collision */ -#define PHY_L_QS_L_STAT (1<<10) /* Bit 10: Link is up */ -#define PHY_L_QS_DUP_MOD (1<<9) /* Bit 9: Full/Half Duplex */ -#define PHY_L_QS_AN (1<<8) /* Bit 8: AutoNeg is On */ -#define PHY_L_QS_AN_C (1<<7) /* Bit 7: AN is Complete */ -#define PHY_L_QS_LLE (7<<4) /* Bit 6: Line Length Estim. */ -#define PHY_L_QS_PAUSE (1<<3) /* Bit 3: LP advertised Pause */ -#define PHY_L_QS_AS_PAUSE (1<<2) /* Bit 2: LP adv. asym. Pause */ -#define PHY_L_QS_ISOLATE (1<<1) /* Bit 1: CIM Isolated */ -#define PHY_L_QS_EVENT (1<<0) /* Bit 0: Event has occurred */ - -/***** PHY_LONE_INT_ENAB 16 bit r/w Interrupt Enable Reg *****/ -/***** PHY_LONE_INT_STAT 16 bit r/o Interrupt Status Reg *****/ - /* Bit 15..14: reserved */ -#define PHY_L_IS_AN_F (1<<13) /* Bit 13: Auto-Negotiation fault */ - /* Bit 12: not described */ -#define PHY_L_IS_CROSS (1<<11) /* Bit 11: Crossover used */ -#define PHY_L_IS_POL (1<<10) /* Bit 10: Polarity correct. used */ -#define PHY_L_IS_SS (1<<9) /* Bit 9: Smart Speed Downgrade */ -#define PHY_L_IS_CFULL (1<<8) /* Bit 8: Counter Full */ -#define PHY_L_IS_AN_C (1<<7) /* Bit 7: AutoNeg Complete */ -#define PHY_L_IS_SPEED (1<<6) /* Bit 6: Speed Changed */ -#define PHY_L_IS_DUP (1<<5) /* Bit 5: Duplex Changed */ -#define PHY_L_IS_LS (1<<4) /* Bit 4: Link Status Changed */ -#define PHY_L_IS_ISOL (1<<3) /* Bit 3: Isolate Occured */ -#define PHY_L_IS_MDINT (1<<2) /* Bit 2: (ro) STAT: MII Int Pending */ -#define PHY_L_IS_INTEN (1<<1) /* Bit 1: ENAB: Enable IRQs */ -#define PHY_L_IS_FORCE (1<<0) /* Bit 0: ENAB: Force Interrupt */ - -/* int. mask */ -#define PHY_L_DEF_MSK (PHY_L_IS_LS | PHY_L_IS_ISOL | PHY_L_IS_INTEN) - -/***** PHY_LONE_LED_CFG 16 bit r/w LED Configuration Reg *****/ -#define PHY_L_LC_LEDC (3<<14) /* Bit 15..14: Col/Blink/On/Off */ -#define PHY_L_LC_LEDR (3<<12) /* Bit 13..12: Rx/Blink/On/Off */ -#define PHY_L_LC_LEDT (3<<10) /* Bit 11..10: Tx/Blink/On/Off */ -#define PHY_L_LC_LEDG (3<<8) /* Bit 9..8: Giga/Blink/On/Off */ -#define PHY_L_LC_LEDS (3<<6) /* Bit 7..6: 10-100/Blink/On/Off */ -#define PHY_L_LC_LEDL (3<<4) /* Bit 5..4: Link/Blink/On/Off */ -#define PHY_L_LC_LEDF (3<<2) /* Bit 3..2: Duplex/Blink/On/Off */ -#define PHY_L_LC_PSTRECH (1<<1) /* Bit 1: Strech LED Pulses */ -#define PHY_L_LC_FREQ (1<<0) /* Bit 0: 30/100 ms */ - -/***** PHY_LONE_PORT_CTRL 16 bit r/w Port Control Reg *****/ -#define PHY_L_PC_TX_TCLK (1<<15) /* Bit 15: Enable TX_TCLK */ - /* Bit 14: reserved */ -#define PHY_L_PC_ALT_NP (1<<13) /* Bit 14: Alternate Next Page */ -#define PHY_L_PC_GMII_ALT (1<<12) /* Bit 13: Alternate GMII driver */ - /* Bit 11: reserved */ -#define PHY_L_PC_TEN_CRS (1<<10) /* Bit 10: Extend CRS*/ - /* Bit 9..0: not described */ - -/***** PHY_LONE_CIM 16 bit r/o CIM Reg *****/ -#define PHY_L_CIM_ISOL (255<<8)/* Bit 15..8: Isolate Count */ -#define PHY_L_CIM_FALSE_CAR (255<<0)/* Bit 7..0: False Carrier Count */ - - -/* - * Pause Bits (PHY_L_AN_ASP and PHY_L_AN_PC) encoding - */ -#define PHY_L_P_NO_PAUSE (0<<10) /* Bit 11..10: no Pause Mode */ -#define PHY_L_P_SYM_MD (1<<10) /* Bit 11..10: symmetric Pause Mode */ -#define PHY_L_P_ASYM_MD (2<<10) /* Bit 11..10: asymmetric Pause Mode */ -#define PHY_L_P_BOTH_MD (3<<10) /* Bit 11..10: both Pause Mode */ - - -/* - * National-Specific - */ -/***** PHY_NAT_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_N_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_N_1000C_MSE (1<<12) /* Bit 12: Master/Slave Enable */ -#define PHY_N_1000C_MSC (1<<11) /* Bit 11: M/S Configuration */ -#define PHY_N_1000C_RD (1<<10) /* Bit 10: Repeater/DTE */ -#define PHY_N_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_N_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ -#define PHY_N_1000C_APC (1<<7) /* Bit 7: Asymmetric Pause Cap. */ - /* Bit 6..0: reserved */ - -/***** PHY_NAT_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -#define PHY_N_1000S_MSF (1<<15) /* Bit 15: Master/Slave Fault */ -#define PHY_N_1000S_MSR (1<<14) /* Bit 14: Master/Slave Result */ -#define PHY_N_1000S_LRS (1<<13) /* Bit 13: Local Receiver Status */ -#define PHY_N_1000S_RRS (1<<12) /* Bit 12: Remote Receiver Status*/ -#define PHY_N_1000S_LP_FD (1<<11) /* Bit 11: Link Partner can FD */ -#define PHY_N_1000S_LP_HD (1<<10) /* Bit 10: Link Partner can HD */ -#define PHY_N_1000C_LP_APC (1<<9) /* Bit 9: LP Asym. Pause Cap. */ - /* Bit 8: reserved */ -#define PHY_N_1000S_IEC 0xff /* Bit 7..0: Idle Error Count */ - -/***** PHY_NAT_EXT_STAT 16 bit r/o Extended Status Register *****/ -#define PHY_N_ES_X_FD_CAP (1<<15) /* Bit 15: 1000Base-X FD capable */ -#define PHY_N_ES_X_HD_CAP (1<<14) /* Bit 14: 1000Base-X HD capable */ -#define PHY_N_ES_T_FD_CAP (1<<13) /* Bit 13: 1000Base-T FD capable */ -#define PHY_N_ES_T_HD_CAP (1<<12) /* Bit 12: 1000Base-T HD capable */ - /* Bit 11..0: reserved */ - -/* todo: those are still missing */ -/***** PHY_NAT_EXT_CTRL1 16 bit r/o Extended Control Reg1 *****/ -/***** PHY_NAT_Q_STAT1 16 bit r/o Quick Status Reg1 *****/ -/***** PHY_NAT_10B_OP 16 bit r/o 10Base-T Operations Reg *****/ -/***** PHY_NAT_EXT_CTRL2 16 bit r/o Extended Control Reg1 *****/ -/***** PHY_NAT_Q_STAT2 16 bit r/o Quick Status Reg2 *****/ -/***** PHY_NAT_PHY_ADDR 16 bit r/o PHY Address Register *****/ - -/* - * Marvell-Specific - */ -/***** PHY_MARV_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/***** PHY_MARV_AUNE_LP 16 bit r/w Link Part Ability Reg *****/ -#define PHY_M_AN_NXT_PG BIT_15 /* Request Next Page */ -#define PHY_M_AN_ACK BIT_14 /* (ro) Acknowledge Received */ -#define PHY_M_AN_RF BIT_13 /* Remote Fault */ - /* Bit 12: reserved */ -#define PHY_M_AN_ASP BIT_11 /* Asymmetric Pause */ -#define PHY_M_AN_PC BIT_10 /* MAC Pause implemented */ -#define PHY_M_AN_100_FD BIT_8 /* Advertise 100Base-TX Full Duplex */ -#define PHY_M_AN_100_HD BIT_7 /* Advertise 100Base-TX Half Duplex */ -#define PHY_M_AN_10_FD BIT_6 /* Advertise 10Base-TX Full Duplex */ -#define PHY_M_AN_10_HD BIT_5 /* Advertise 10Base-TX Half Duplex */ - -/* special defines for FIBER (88E1011S only) */ -#define PHY_M_AN_ASP_X BIT_8 /* Asymmetric Pause */ -#define PHY_M_AN_PC_X BIT_7 /* MAC Pause implemented */ -#define PHY_M_AN_1000X_AHD BIT_6 /* Advertise 10000Base-X Half Duplex */ -#define PHY_M_AN_1000X_AFD BIT_5 /* Advertise 10000Base-X Full Duplex */ - -/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ -#define PHY_M_P_NO_PAUSE_X (0<<7) /* Bit 8.. 7: no Pause Mode */ -#define PHY_M_P_SYM_MD_X (1<<7) /* Bit 8.. 7: symmetric Pause Mode */ -#define PHY_M_P_ASYM_MD_X (2<<7) /* Bit 8.. 7: asymmetric Pause Mode */ -#define PHY_M_P_BOTH_MD_X (3<<7) /* Bit 8.. 7: both Pause Mode */ - -/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -#define PHY_M_1000C_TEST (7<<13) /* Bit 15..13: Test Modes */ -#define PHY_M_1000C_MSE (1<<12) /* Bit 12: Manual Master/Slave Enable */ -#define PHY_M_1000C_MSC (1<<11) /* Bit 11: M/S Configuration (1=Master) */ -#define PHY_M_1000C_MPD (1<<10) /* Bit 10: Multi-Port Device */ -#define PHY_M_1000C_AFD (1<<9) /* Bit 9: Advertise Full Duplex */ -#define PHY_M_1000C_AHD (1<<8) /* Bit 8: Advertise Half Duplex */ - /* Bit 7..0: reserved */ - -/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ -#define PHY_M_PC_TX_FFD_MSK (3<<14) /* Bit 15..14: Tx FIFO Depth Mask */ -#define PHY_M_PC_RX_FFD_MSK (3<<12) /* Bit 13..12: Rx FIFO Depth Mask */ -#define PHY_M_PC_ASS_CRS_TX (1<<11) /* Bit 11: Assert CRS on Transmit */ -#define PHY_M_PC_FL_GOOD (1<<10) /* Bit 10: Force Link Good */ -#define PHY_M_PC_EN_DET_MSK (3<<8) /* Bit 9.. 8: Energy Detect Mask */ -#define PHY_M_PC_ENA_EXT_D (1<<7) /* Bit 7: Enable Ext. Distance (10BT) */ -#define PHY_M_PC_MDIX_MSK (3<<5) /* Bit 6.. 5: MDI/MDIX Config. Mask */ -#define PHY_M_PC_DIS_125CLK (1<<4) /* Bit 4: Disable 125 CLK */ -#define PHY_M_PC_MAC_POW_UP (1<<3) /* Bit 3: MAC Power up */ -#define PHY_M_PC_SQE_T_ENA (1<<2) /* Bit 2: SQE Test Enabled */ -#define PHY_M_PC_POL_R_DIS (1<<1) /* Bit 1: Polarity Reversal Disabled */ -#define PHY_M_PC_DIS_JABBER (1<<0) /* Bit 0: Disable Jabber */ - -#define PHY_M_PC_EN_DET SHIFT8(2) /* Energy Detect (Mode 1) */ -#define PHY_M_PC_EN_DET_PLUS SHIFT8(3) /* Energy Detect Plus (Mode 2) */ - -#define PHY_M_PC_MDI_XMODE(x) SHIFT5(x) -#define PHY_M_PC_MAN_MDI 0 /* 00 = Manual MDI configuration */ -#define PHY_M_PC_MAN_MDIX 1 /* 01 = Manual MDIX configuration */ -#define PHY_M_PC_ENA_AUTO 3 /* 11 = Enable Automatic Crossover */ - -/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ -#define PHY_M_PS_SPEED_MSK (3<<14) /* Bit 15..14: Speed Mask */ -#define PHY_M_PS_SPEED_1000 (1<<15) /* 10 = 1000 Mbps */ -#define PHY_M_PS_SPEED_100 (1<<14) /* 01 = 100 Mbps */ -#define PHY_M_PS_SPEED_10 0 /* 00 = 10 Mbps */ -#define PHY_M_PS_FULL_DUP (1<<13) /* Bit 13: Full Duplex */ -#define PHY_M_PS_PAGE_REC (1<<12) /* Bit 12: Page Received */ -#define PHY_M_PS_SPDUP_RES (1<<11) /* Bit 11: Speed & Duplex Resolved */ -#define PHY_M_PS_LINK_UP (1<<10) /* Bit 10: Link Up */ -#define PHY_M_PS_CABLE_MSK (3<<7) /* Bit 9.. 7: Cable Length Mask */ -#define PHY_M_PS_MDI_X_STAT (1<<6) /* Bit 6: MDI Crossover Stat (1=MDIX) */ -#define PHY_M_PS_DOWNS_STAT (1<<5) /* Bit 5: Downshift Status (1=downsh.) */ -#define PHY_M_PS_ENDET_STAT (1<<4) /* Bit 4: Energy Detect Status (1=act) */ -#define PHY_M_PS_TX_P_EN (1<<3) /* Bit 3: Tx Pause Enabled */ -#define PHY_M_PS_RX_P_EN (1<<2) /* Bit 2: Rx Pause Enabled */ -#define PHY_M_PS_POL_REV (1<<1) /* Bit 1: Polarity Reversed */ -#define PHY_M_PC_JABBER (1<<0) /* Bit 0: Jabber */ - -#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) - -/***** PHY_MARV_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ -/***** PHY_MARV_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -#define PHY_M_IS_AN_ERROR (1<<15) /* Bit 15: Auto-Negotiation Error */ -#define PHY_M_IS_LSP_CHANGE (1<<14) /* Bit 14: Link Speed Changed */ -#define PHY_M_IS_DUP_CHANGE (1<<13) /* Bit 13: Duplex Mode Changed */ -#define PHY_M_IS_AN_PR (1<<12) /* Bit 12: Page Received */ -#define PHY_M_IS_AN_COMPL (1<<11) /* Bit 11: Auto-Negotiation Completed */ -#define PHY_M_IS_LST_CHANGE (1<<10) /* Bit 10: Link Status Changed */ -#define PHY_M_IS_SYMB_ERROR (1<<9) /* Bit 9: Symbol Error */ -#define PHY_M_IS_FALSE_CARR (1<<8) /* Bit 8: False Carrier */ -#define PHY_M_IS_FIFO_ERROR (1<<7) /* Bit 7: FIFO Overflow/Underrun Error */ -#define PHY_M_IS_MDI_CHANGE (1<<6) /* Bit 6: MDI Crossover Changed */ -#define PHY_M_IS_DOWNSH_DET (1<<5) /* Bit 5: Downshift Detected */ -#define PHY_M_IS_END_CHANGE (1<<4) /* Bit 4: Energy Detect Changed */ - /* Bit 3..2: reserved */ -#define PHY_M_IS_POL_CHANGE (1<<1) /* Bit 1: Polarity Changed */ -#define PHY_M_IS_JABBER (1<<0) /* Bit 0: Jabber */ - -#define PHY_M_DEF_MSK (PHY_M_IS_AN_ERROR | PHY_M_IS_AN_PR | \ - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR) - -/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ -#define PHY_M_EC_M_DSC_MSK (3<<10) /* Bit 11..10: Master downshift counter */ -#define PHY_M_EC_S_DSC_MSK (3<<8) /* Bit 9.. 8: Slave downshift counter */ -#define PHY_M_EC_MAC_S_MSK (7<<4) /* Bit 6.. 4: Def. MAC interface speed */ -#define PHY_M_EC_FIB_AN_ENA (1<<3) /* Bit 3: Fiber Auto-Neg. Enable */ - -#define PHY_M_EC_M_DSC(x) SHIFT10(x) /* 00=1x; 01=2x; 10=3x; 11=4x */ -#define PHY_M_EC_S_DSC(x) SHIFT8(x) /* 00=dis; 01=1x; 10=2x; 11=3x */ -#define PHY_M_EC_MAC_S(x) SHIFT4(x) /* 01X=0; 110=2.5; 111=25 (MHz) */ - -#define MAC_TX_CLK_0_MHZ 2 -#define MAC_TX_CLK_2_5_MHZ 6 -#define MAC_TX_CLK_25_MHZ 7 - -/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ -#define PHY_M_LEDC_DIS_LED (1<<15) /* Bit 15: Disable LED */ -#define PHY_M_LEDC_PULS_MSK (7<<12) /* Bit 14..12: Pulse Stretch Mask */ -#define PHY_M_LEDC_F_INT (1<<11) /* Bit 11: Force Interrupt */ -#define PHY_M_LEDC_BL_R_MSK (7<<8) /* Bit 10.. 8: Blink Rate Mask */ - /* Bit 7.. 5: reserved */ -#define PHY_M_LEDC_LINK_MSK (3<<3) /* Bit 4.. 3: Link Control Mask */ -#define PHY_M_LEDC_DP_CTRL (1<<2) /* Bit 2: Duplex Control */ -#define PHY_M_LEDC_RX_CTRL (1<<1) /* Bit 1: Rx activity / Link */ -#define PHY_M_LEDC_TX_CTRL (1<<0) /* Bit 0: Tx activity / Link */ - -#define PHY_M_LED_PULS_DUR(x) SHIFT12(x) /* Pulse Stretch Duration */ - -#define PULS_NO_STR 0 /* no pulse stretching */ -#define PULS_21MS 1 /* 21 ms to 42 ms */ -#define PULS_42MS 2 /* 42 ms to 84 ms */ -#define PULS_84MS 3 /* 84 ms to 170 ms */ -#define PULS_170MS 4 /* 170 ms to 340 ms */ -#define PULS_340MS 5 /* 340 ms to 670 ms */ -#define PULS_670MS 6 /* 670 ms to 1.3 s */ -#define PULS_1300MS 7 /* 1.3 s to 2.7 s */ - -#define PHY_M_LED_BLINK_RT(x) SHIFT8(x) /* Blink Rate */ - -#define BLINK_42MS 0 /* 42 ms */ -#define BLINK_84MS 1 /* 84 ms */ -#define BLINK_170MS 2 /* 170 ms */ -#define BLINK_340MS 3 /* 340 ms */ -#define BLINK_670MS 4 /* 670 ms */ - /* values 5 - 7: reserved */ - -/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ -#define PHY_M_LED_MO_DUP(x) SHIFT10(x) /* Bit 11..10: Duplex */ -#define PHY_M_LED_MO_10(x) SHIFT8(x) /* Bit 9.. 8: Link 10 */ -#define PHY_M_LED_MO_100(x) SHIFT6(x) /* Bit 7.. 6: Link 100 */ -#define PHY_M_LED_MO_1000(x) SHIFT4(x) /* Bit 5.. 4: Link 1000 */ -#define PHY_M_LED_MO_RX(x) SHIFT2(x) /* Bit 3.. 2: Rx */ -#define PHY_M_LED_MO_TX(x) SHIFT0(x) /* Bit 1.. 0: Tx */ - -#define MO_LED_NORM 0 -#define MO_LED_BLINK 1 -#define MO_LED_OFF 2 -#define MO_LED_ON 3 - -/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ - /* Bit 15.. 7: reserved */ -#define PHY_M_EC2_FI_IMPED (1<<6) /* Bit 6: Fiber Input Impedance */ -#define PHY_M_EC2_FO_IMPED (1<<5) /* Bit 5: Fiber Output Impedance */ -#define PHY_M_EC2_FO_M_CLK (1<<4) /* Bit 4: Fiber Mode Clock Enable */ -#define PHY_M_EC2_FO_BOOST (1<<3) /* Bit 3: Fiber Output Boost */ -#define PHY_M_EC2_FO_AM_MSK 7 /* Bit 2.. 0: Fiber Output Amplitude */ - -/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ -#define PHY_M_FC_AUTO_SEL (1<<15) /* Bit 15: Fiber/Copper Auto Sel. dis. */ -#define PHY_M_FC_AN_REG_ACC (1<<14) /* Bit 14: Fiber/Copper Autoneg. reg acc */ -#define PHY_M_FC_RESULUTION (1<<13) /* Bit 13: Fiber/Copper Resulution */ -#define PHY_M_SER_IF_AN_BP (1<<12) /* Bit 12: Ser IF autoneg. bypass enable */ -#define PHY_M_SER_IF_BP_ST (1<<11) /* Bit 11: Ser IF autoneg. bypass status */ -#define PHY_M_IRQ_POLARITY (1<<10) /* Bit 10: IRQ polarity */ - /* Bit 9..4: reserved */ -#define PHY_M_UNDOC1 (1<< 7) /* undocumented bit !! */ -#define PHY_M_MODE_MASK (0xf<<0)/* Bit 3..0: copy of HWCFG MODE[3:0] */ - - -/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ -#define PHY_M_CABD_ENA_TEST (1<<15) /* Bit 15: Enable Test */ -#define PHY_M_CABD_STAT_MSK (3<<13) /* Bit 14..13: Status */ - /* Bit 12.. 8: reserved */ -#define PHY_M_CABD_DIST_MSK 0xff /* Bit 7.. 0: Distance */ - -/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */ -#define CABD_STAT_NORMAL 0 -#define CABD_STAT_SHORT 1 -#define CABD_STAT_OPEN 2 -#define CABD_STAT_FAIL 3 - - -/* - * GMAC registers - * - * The GMAC registers are 16 or 32 bits wide. - * The GMACs host processor interface is 16 bits wide, - * therefore ALL registers will be addressed with 16 bit accesses. - * - * The following macros are provided to access the GMAC registers - * GM_IN16(), GM_OUT16, GM_IN32(), GM_OUT32(), GM_INADR(), GM_OUTADR(), - * GM_INHASH(), and GM_OUTHASH(). - * The macros are defined in SkGeHw.h. - * - * Note: NA reg = Network Address e.g DA, SA etc. - * - */ - -/* Port Registers */ -#define GM_GP_STAT 0x0000 /* 16 bit r/o General Purpose Status */ -#define GM_GP_CTRL 0x0004 /* 16 bit r/w General Purpose Control */ -#define GM_TX_CTRL 0x0008 /* 16 bit r/w Transmit Control Reg. */ -#define GM_RX_CTRL 0x000c /* 16 bit r/w Receive Control Reg. */ -#define GM_TX_FLOW_CTRL 0x0010 /* 16 bit r/w Transmit Flow-Control */ -#define GM_TX_PARAM 0x0014 /* 16 bit r/w Transmit Parameter Reg. */ -#define GM_SERIAL_MODE 0x0018 /* 16 bit r/w Serial Mode Register */ - -/* Source Address Registers */ -#define GM_SRC_ADDR_1L 0x001c /* 16 bit r/w Source Address 1 (low) */ -#define GM_SRC_ADDR_1M 0x0020 /* 16 bit r/w Source Address 1 (middle) */ -#define GM_SRC_ADDR_1H 0x0024 /* 16 bit r/w Source Address 1 (high) */ -#define GM_SRC_ADDR_2L 0x0028 /* 16 bit r/w Source Address 2 (low) */ -#define GM_SRC_ADDR_2M 0x002c /* 16 bit r/w Source Address 2 (middle) */ -#define GM_SRC_ADDR_2H 0x0030 /* 16 bit r/w Source Address 2 (high) */ - -/* Multicast Address Hash Registers */ -#define GM_MC_ADDR_H1 0x0034 /* 16 bit r/w Multicast Address Hash 1 */ -#define GM_MC_ADDR_H2 0x0038 /* 16 bit r/w Multicast Address Hash 2 */ -#define GM_MC_ADDR_H3 0x003c /* 16 bit r/w Multicast Address Hash 3 */ -#define GM_MC_ADDR_H4 0x0040 /* 16 bit r/w Multicast Address Hash 4 */ - -/* Interrupt Source Registers */ -#define GM_TX_IRQ_SRC 0x0044 /* 16 bit r/o Tx Overflow IRQ Source */ -#define GM_RX_IRQ_SRC 0x0048 /* 16 bit r/o Rx Overflow IRQ Source */ -#define GM_TR_IRQ_SRC 0x004c /* 16 bit r/o Tx/Rx Over. IRQ Source */ - -/* Interrupt Mask Registers */ -#define GM_TX_IRQ_MSK 0x0050 /* 16 bit r/w Tx Overflow IRQ Mask */ -#define GM_RX_IRQ_MSK 0x0054 /* 16 bit r/w Rx Overflow IRQ Mask */ -#define GM_TR_IRQ_MSK 0x0058 /* 16 bit r/w Tx/Rx Over. IRQ Mask */ - -/* Serial Management Interface (SMI) Registers */ -#define GM_SMI_CTRL 0x0080 /* 16 bit r/w SMI Control Register */ -#define GM_SMI_DATA 0x0084 /* 16 bit r/w SMI Data Register */ -#define GM_PHY_ADDR 0x0088 /* 16 bit r/w GPHY Address Register */ - -/* MIB Counters */ -#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ -#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ - -/* - * MIB Counters base address definitions (low word) - - * use offset 4 for access to high word (32 bit r/o) - */ -#define GM_RXF_UC_OK \ - (GM_MIB_CNT_BASE + 0) /* Unicast Frames Received OK */ -#define GM_RXF_BC_OK \ - (GM_MIB_CNT_BASE + 8) /* Broadcast Frames Received OK */ -#define GM_RXF_MPAUSE \ - (GM_MIB_CNT_BASE + 16) /* Pause MAC Ctrl Frames Received */ -#define GM_RXF_MC_OK \ - (GM_MIB_CNT_BASE + 24) /* Multicast Frames Received OK */ -#define GM_RXF_FCS_ERR \ - (GM_MIB_CNT_BASE + 32) /* Rx Frame Check Seq. Error */ - /* GM_MIB_CNT_BASE + 40: reserved */ -#define GM_RXO_OK_LO \ - (GM_MIB_CNT_BASE + 48) /* Octets Received OK Low */ -#define GM_RXO_OK_HI \ - (GM_MIB_CNT_BASE + 56) /* Octets Received OK High */ -#define GM_RXO_ERR_LO \ - (GM_MIB_CNT_BASE + 64) /* Octets Received Invalid Low */ -#define GM_RXO_ERR_HI \ - (GM_MIB_CNT_BASE + 72) /* Octets Received Invalid High */ -#define GM_RXF_SHT \ - (GM_MIB_CNT_BASE + 80) /* Frames <64 Byte Received OK */ -#define GM_RXE_FRAG \ - (GM_MIB_CNT_BASE + 88) /* Frames <64 Byte Received with FCS Err */ -#define GM_RXF_64B \ - (GM_MIB_CNT_BASE + 96) /* 64 Byte Rx Frame */ -#define GM_RXF_127B \ - (GM_MIB_CNT_BASE + 104) /* 65-127 Byte Rx Frame */ -#define GM_RXF_255B \ - (GM_MIB_CNT_BASE + 112) /* 128-255 Byte Rx Frame */ -#define GM_RXF_511B \ - (GM_MIB_CNT_BASE + 120) /* 256-511 Byte Rx Frame */ -#define GM_RXF_1023B \ - (GM_MIB_CNT_BASE + 128) /* 512-1023 Byte Rx Frame */ -#define GM_RXF_1518B \ - (GM_MIB_CNT_BASE + 136) /* 1024-1518 Byte Rx Frame */ -#define GM_RXF_MAX_SZ \ - (GM_MIB_CNT_BASE + 144) /* 1519-MaxSize Byte Rx Frame */ -#define GM_RXF_LNG_ERR \ - (GM_MIB_CNT_BASE + 152) /* Rx Frame too Long Error */ -#define GM_RXF_JAB_PKT \ - (GM_MIB_CNT_BASE + 160) /* Rx Jabber Packet Frame */ - /* GM_MIB_CNT_BASE + 168: reserved */ -#define GM_RXE_FIFO_OV \ - (GM_MIB_CNT_BASE + 176) /* Rx FIFO overflow Event */ - /* GM_MIB_CNT_BASE + 184: reserved */ -#define GM_TXF_UC_OK \ - (GM_MIB_CNT_BASE + 192) /* Unicast Frames Xmitted OK */ -#define GM_TXF_BC_OK \ - (GM_MIB_CNT_BASE + 200) /* Broadcast Frames Xmitted OK */ -#define GM_TXF_MPAUSE \ - (GM_MIB_CNT_BASE + 208) /* Pause MAC Ctrl Frames Xmitted */ -#define GM_TXF_MC_OK \ - (GM_MIB_CNT_BASE + 216) /* Multicast Frames Xmitted OK */ -#define GM_TXO_OK_LO \ - (GM_MIB_CNT_BASE + 224) /* Octets Transmitted OK Low */ -#define GM_TXO_OK_HI \ - (GM_MIB_CNT_BASE + 232) /* Octets Transmitted OK High */ -#define GM_TXF_64B \ - (GM_MIB_CNT_BASE + 240) /* 64 Byte Tx Frame */ -#define GM_TXF_127B \ - (GM_MIB_CNT_BASE + 248) /* 65-127 Byte Tx Frame */ -#define GM_TXF_255B \ - (GM_MIB_CNT_BASE + 256) /* 128-255 Byte Tx Frame */ -#define GM_TXF_511B \ - (GM_MIB_CNT_BASE + 264) /* 256-511 Byte Tx Frame */ -#define GM_TXF_1023B \ - (GM_MIB_CNT_BASE + 272) /* 512-1023 Byte Tx Frame */ -#define GM_TXF_1518B \ - (GM_MIB_CNT_BASE + 280) /* 1024-1518 Byte Tx Frame */ -#define GM_TXF_MAX_SZ \ - (GM_MIB_CNT_BASE + 288) /* 1519-MaxSize Byte Tx Frame */ - /* GM_MIB_CNT_BASE + 296: reserved */ -#define GM_TXF_COL \ - (GM_MIB_CNT_BASE + 304) /* Tx Collision */ -#define GM_TXF_LAT_COL \ - (GM_MIB_CNT_BASE + 312) /* Tx Late Collision */ -#define GM_TXF_ABO_COL \ - (GM_MIB_CNT_BASE + 320) /* Tx aborted due to Exces. Col. */ -#define GM_TXF_MUL_COL \ - (GM_MIB_CNT_BASE + 328) /* Tx Multiple Collision */ -#define GM_TXF_SNG_COL \ - (GM_MIB_CNT_BASE + 336) /* Tx Single Collision */ -#define GM_TXE_FIFO_UR \ - (GM_MIB_CNT_BASE + 344) /* Tx FIFO Underrun Event */ - -/*----------------------------------------------------------------------------*/ -/* - * GMAC Bit Definitions - * - * If the bit access behaviour differs from the register access behaviour - * (r/w, r/o) this is documented after the bit number. - * The following bit access behaviours are used: - * (sc) self clearing - * (r/o) read only - */ - -/* GM_GP_STAT 16 bit r/o General Purpose Status Register */ -#define GM_GPSR_SPEED (1<<15) /* Bit 15: Port Speed (1 = 100 Mbps) */ -#define GM_GPSR_DUPLEX (1<<14) /* Bit 14: Duplex Mode (1 = Full) */ -#define GM_GPSR_FC_TX_DIS (1<<13) /* Bit 13: Tx Flow-Control Mode Disabled */ -#define GM_GPSR_LINK_UP (1<<12) /* Bit 12: Link Up Status */ -#define GM_GPSR_PAUSE (1<<11) /* Bit 11: Pause State */ -#define GM_GPSR_TX_ACTIVE (1<<10) /* Bit 10: Tx in Progress */ -#define GM_GPSR_EXC_COL (1<<9) /* Bit 9: Excessive Collisions Occured */ -#define GM_GPSR_LAT_COL (1<<8) /* Bit 8: Late Collisions Occured */ - /* Bit 7..6: reserved */ -#define GM_GPSR_PHY_ST_CH (1<<5) /* Bit 5: PHY Status Change */ -#define GM_GPSR_GIG_SPEED (1<<4) /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ -#define GM_GPSR_PART_MODE (1<<3) /* Bit 3: Partition mode */ -#define GM_GPSR_FC_RX_DIS (1<<2) /* Bit 2: Rx Flow-Control Mode Disabled */ -#define GM_GPSR_PROM_EN (1<<1) /* Bit 1: Promiscuous Mode Enabled */ - /* Bit 0: reserved */ - -/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ - /* Bit 15: reserved */ -#define GM_GPCR_PROM_ENA (1<<14) /* Bit 14: Enable Promiscuous Mode */ -#define GM_GPCR_FC_TX_DIS (1<<13) /* Bit 13: Disable Tx Flow-Control Mode */ -#define GM_GPCR_TX_ENA (1<<12) /* Bit 12: Enable Transmit */ -#define GM_GPCR_RX_ENA (1<<11) /* Bit 11: Enable Receive */ -#define GM_GPCR_BURST_ENA (1<<10) /* Bit 10: Enable Burst Mode */ -#define GM_GPCR_LOOP_ENA (1<<9) /* Bit 9: Enable MAC Loopback Mode */ -#define GM_GPCR_PART_ENA (1<<8) /* Bit 8: Enable Partition Mode */ -#define GM_GPCR_GIGS_ENA (1<<7) /* Bit 7: Gigabit Speed (1000 Mbps) */ -#define GM_GPCR_FL_PASS (1<<6) /* Bit 6: Force Link Pass */ -#define GM_GPCR_DUP_FULL (1<<5) /* Bit 5: Full Duplex Mode */ -#define GM_GPCR_FC_RX_DIS (1<<4) /* Bit 4: Disable Rx Flow-Control Mode */ -#define GM_GPCR_SPEED_100 (1<<3) /* Bit 3: Port Speed 100 Mbps */ -#define GM_GPCR_AU_DUP_DIS (1<<2) /* Bit 2: Disable Auto-Update Duplex */ -#define GM_GPCR_AU_FCT_DIS (1<<1) /* Bit 1: Disable Auto-Update Flow-C. */ -#define GM_GPCR_AU_SPD_DIS (1<<0) /* Bit 0: Disable Auto-Update Speed */ - -#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) -#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS |\ - GM_GPCR_AU_SPD_DIS) - -/* GM_TX_CTRL 16 bit r/w Transmit Control Register */ -#define GM_TXCR_FORCE_JAM (1<<15) /* Bit 15: Force Jam / Flow-Control */ -#define GM_TXCR_CRC_DIS (1<<14) /* Bit 14: Disable insertion of CRC */ -#define GM_TXCR_PAD_DIS (1<<13) /* Bit 13: Disable padding of packets */ -#define GM_TXCR_COL_THR_MSK (7<<10) /* Bit 12..10: Collision Threshold */ - -#define TX_COL_THR(x) (SHIFT10(x) & GM_TXCR_COL_THR_MSK) - -#define TX_COL_DEF 0x04 - -/* GM_RX_CTRL 16 bit r/w Receive Control Register */ -#define GM_RXCR_UCF_ENA (1<<15) /* Bit 15: Enable Unicast filtering */ -#define GM_RXCR_MCF_ENA (1<<14) /* Bit 14: Enable Multicast filtering */ -#define GM_RXCR_CRC_DIS (1<<13) /* Bit 13: Remove 4-byte CRC */ -#define GM_RXCR_PASS_FC (1<<12) /* Bit 12: Pass FC packets to FIFO */ - -/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ -#define GM_TXPA_JAMLEN_MSK (0x03<<14) /* Bit 15..14: Jam Length */ -#define GM_TXPA_JAMIPG_MSK (0x1f<<9) /* Bit 13..9: Jam IPG */ -#define GM_TXPA_JAMDAT_MSK (0x1f<<4) /* Bit 8..4: IPG Jam to Data */ - /* Bit 3..0: reserved */ - -#define TX_JAM_LEN_VAL(x) (SHIFT14(x) & GM_TXPA_JAMLEN_MSK) -#define TX_JAM_IPG_VAL(x) (SHIFT9(x) & GM_TXPA_JAMIPG_MSK) -#define TX_IPG_JAM_DATA(x) (SHIFT4(x) & GM_TXPA_JAMDAT_MSK) - -#define TX_JAM_LEN_DEF 0x03 -#define TX_JAM_IPG_DEF 0x0b -#define TX_IPG_JAM_DEF 0x1c - -/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ -#define GM_SMOD_DATABL_MSK (0x1f<<11) /* Bit 15..11: Data Blinder (r/o) */ -#define GM_SMOD_LIMIT_4 (1<<10) /* Bit 10: 4 consecutive Tx trials */ -#define GM_SMOD_VLAN_ENA (1<<9) /* Bit 9: Enable VLAN (Max. Frame Len) */ -#define GM_SMOD_JUMBO_ENA (1<<8) /* Bit 8: Enable Jumbo (Max. Frame Len) */ - /* Bit 7..5: reserved */ -#define GM_SMOD_IPG_MSK 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ - -#define DATA_BLIND_VAL(x) (SHIFT11(x) & GM_SMOD_DATABL_MSK) -#define DATA_BLIND_DEF 0x04 - -#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK) -#define IPG_DATA_DEF 0x1e - -/* GM_SMI_CTRL 16 bit r/w SMI Control Register */ -#define GM_SMI_CT_PHY_A_MSK (0x1f<<11) /* Bit 15..11: PHY Device Address */ -#define GM_SMI_CT_REG_A_MSK (0x1f<<6) /* Bit 10.. 6: PHY Register Address */ -#define GM_SMI_CT_OP_RD (1<<5) /* Bit 5: OpCode Read (0=Write)*/ -#define GM_SMI_CT_RD_VAL (1<<4) /* Bit 4: Read Valid (Read completed) */ -#define GM_SMI_CT_BUSY (1<<3) /* Bit 3: Busy (Operation in progress) */ - /* Bit 2..0: reserved */ - -#define GM_SMI_CT_PHY_AD(x) (SHIFT11(x) & GM_SMI_CT_PHY_A_MSK) -#define GM_SMI_CT_REG_AD(x) (SHIFT6(x) & GM_SMI_CT_REG_A_MSK) - - /* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ - /* Bit 15..6: reserved */ -#define GM_PAR_MIB_CLR (1<<5) /* Bit 5: Set MIB Clear Counter Mode */ -#define GM_PAR_MIB_TST (1<<4) /* Bit 4: MIB Load Counter (Test Mode) */ - /* Bit 3..0: reserved */ - -/* Receive Frame Status Encoding */ -#define GMR_FS_LEN (0xffffUL<<16) /* Bit 31..16: Rx Frame Length */ - /* Bit 15..14: reserved */ -#define GMR_FS_VLAN (1L<<13) /* Bit 13: VLAN Packet */ -#define GMR_FS_JABBER (1L<<12) /* Bit 12: Jabber Packet */ -#define GMR_FS_UN_SIZE (1L<<11) /* Bit 11: Undersize Packet */ -#define GMR_FS_MC (1L<<10) /* Bit 10: Multicast Packet */ -#define GMR_FS_BC (1L<<9) /* Bit 9: Broadcast Packet */ -#define GMR_FS_RX_OK (1L<<8) /* Bit 8: Receive OK (Good Packet) */ -#define GMR_FS_GOOD_FC (1L<<7) /* Bit 7: Good Flow-Control Packet */ -#define GMR_FS_BAD_FC (1L<<6) /* Bit 6: Bad Flow-Control Packet */ -#define GMR_FS_MII_ERR (1L<<5) /* Bit 5: MII Error */ -#define GMR_FS_LONG_ERR (1L<<4) /* Bit 4: Too Long Packet */ -#define GMR_FS_FRAGMENT (1L<<3) /* Bit 3: Fragment */ - /* Bit 2: reserved */ -#define GMR_FS_CRC_ERR (1L<<1) /* Bit 1: CRC Error */ -#define GMR_FS_RX_FF_OV (1L<<0) /* Bit 0: Rx FIFO Overflow */ - -/* - * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) - */ -#define GMR_FS_ANY_ERR (GMR_FS_CRC_ERR | \ - GMR_FS_LONG_ERR | \ - GMR_FS_MII_ERR | \ - GMR_FS_BAD_FC | \ - GMR_FS_GOOD_FC | \ - GMR_FS_JABBER) - -/* Rx GMAC FIFO Flush Mask (default) */ -#define RX_FF_FL_DEF_MSK (GMR_FS_CRC_ERR | \ - GMR_FS_RX_FF_OV | \ - GMR_FS_MII_ERR | \ - GMR_FS_BAD_FC | \ - GMR_FS_GOOD_FC | \ - GMR_FS_UN_SIZE | \ - GMR_FS_JABBER) - -/* typedefs *******************************************************************/ - - -/* function prototypes ********************************************************/ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* __INC_XMAC_H */ diff --git a/drivers/net/sk98lin/skaddr.c b/drivers/net/sk98lin/skaddr.c deleted file mode 100644 index 6e6c56aa6d6f..000000000000 --- a/drivers/net/sk98lin/skaddr.c +++ /dev/null @@ -1,1788 +0,0 @@ -/****************************************************************************** - * - * Name: skaddr.c - * Project: Gigabit Ethernet Adapters, ADDR-Module - * Version: $Revision: 1.52 $ - * Date: $Date: 2003/06/02 13:46:15 $ - * Purpose: Manage Addresses (Multicast and Unicast) and Promiscuous Mode. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module is intended to manage multicast addresses, address override, - * and promiscuous mode on GEnesis and Yukon adapters. - * - * Address Layout: - * port address: physical MAC address - * 1st exact match: logical MAC address (GEnesis only) - * 2nd exact match: RLMT multicast (GEnesis only) - * exact match 3-13: OS-specific multicasts (GEnesis only) - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * "skdrv2nd.h" - * - ******************************************************************************/ - -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skaddr.c,v 1.52 2003/06/02 13:46:15 tschilli Exp $ (C) Marvell."; -#endif /* DEBUG ||!LINT || !SK_SLIM */ - -#define __SKADDR_C - -#ifdef __cplusplus -extern "C" { -#endif /* cplusplus */ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* defines ********************************************************************/ - - -#define XMAC_POLY 0xEDB88320UL /* CRC32-Poly - XMAC: Little Endian */ -#define GMAC_POLY 0x04C11DB7L /* CRC16-Poly - GMAC: Little Endian */ -#define HASH_BITS 6 /* #bits in hash */ -#define SK_MC_BIT 0x01 - -/* Error numbers and messages. */ - -#define SKERR_ADDR_E001 (SK_ERRBASE_ADDR + 0) -#define SKERR_ADDR_E001MSG "Bad Flags." -#define SKERR_ADDR_E002 (SKERR_ADDR_E001 + 1) -#define SKERR_ADDR_E002MSG "New Error." - -/* typedefs *******************************************************************/ - -/* None. */ - -/* global variables ***********************************************************/ - -/* 64-bit hash values with all bits set. */ - -static const SK_U16 OnesHash[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; - -/* local variables ************************************************************/ - -#ifdef DEBUG -static int Next0[SK_MAX_MACS] = {0}; -#endif /* DEBUG */ - -static int SkAddrGmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - SK_MAC_ADDR *pMc, int Flags); -static int SkAddrGmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - int Flags); -static int SkAddrGmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber); -static int SkAddrGmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC, - SK_U32 PortNumber, int NewPromMode); -static int SkAddrXmacMcAdd(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - SK_MAC_ADDR *pMc, int Flags); -static int SkAddrXmacMcClear(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber, - int Flags); -static int SkAddrXmacMcUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 PortNumber); -static int SkAddrXmacPromiscuousChange(SK_AC *pAC, SK_IOC IoC, - SK_U32 PortNumber, int NewPromMode); - -/* functions ******************************************************************/ - -/****************************************************************************** - * - * SkAddrInit - initialize data, set state to init - * - * Description: - * - * SK_INIT_DATA - * ============ - * - * This routine clears the multicast tables and resets promiscuous mode. - * Some entries are reserved for the "logical MAC address", the - * SK-RLMT multicast address, and the BPDU multicast address. - * - * - * SK_INIT_IO - * ========== - * - * All permanent MAC addresses are read from EPROM. - * If the current MAC addresses are not already set in software, - * they are set to the values of the permanent addresses. - * The current addresses are written to the corresponding MAC. - * - * - * SK_INIT_RUN - * =========== - * - * Nothing. - * - * Context: - * init, pageable - * - * Returns: - * SK_ADDR_SUCCESS - */ -int SkAddrInit( -SK_AC *pAC, /* the adapter context */ -SK_IOC IoC, /* I/O context */ -int Level) /* initialization level */ -{ - int j; - SK_U32 i; - SK_U8 *InAddr; - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - switch (Level) { - case SK_INIT_DATA: - SK_MEMSET((char *) &pAC->Addr, (SK_U8) 0, - (SK_U16) sizeof(SK_ADDR)); - - for (i = 0; i < SK_MAX_MACS; i++) { - pAPort = &pAC->Addr.Port[i]; - pAPort->PromMode = SK_PROM_MODE_NONE; - - pAPort->FirstExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - pAPort->FirstExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - pAPort->NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - pAPort->NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - } -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 4; - } - } -#endif /* DEBUG */ - /* pAC->Addr.InitDone = SK_INIT_DATA; */ - break; - - case SK_INIT_IO: -#ifndef SK_NO_RLMT - for (i = 0; i < SK_MAX_NETS; i++) { - pAC->Addr.Net[i].ActivePort = pAC->Rlmt.Net[i].ActivePort; - } -#endif /* !SK_NO_RLMT */ -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 8; - } - } -#endif /* DEBUG */ - - /* Read permanent logical MAC address from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - InAddr = (SK_U8 *) &pAC->Addr.Net[0].PermanentMacAddress.a[j]; - SK_IN8(IoC, B2_MAC_1 + j, InAddr); - } - - if (!pAC->Addr.Net[0].CurrentMacAddressSet) { - /* Set the current logical MAC address to the permanent one. */ - pAC->Addr.Net[0].CurrentMacAddress = - pAC->Addr.Net[0].PermanentMacAddress; - pAC->Addr.Net[0].CurrentMacAddressSet = SK_TRUE; - } - - /* Set the current logical MAC address. */ - pAC->Addr.Port[pAC->Addr.Net[0].ActivePort].Exact[0] = - pAC->Addr.Net[0].CurrentMacAddress; -#if SK_MAX_NETS > 1 - /* Set logical MAC address for net 2 to (log | 3). */ - if (!pAC->Addr.Net[1].CurrentMacAddressSet) { - pAC->Addr.Net[1].PermanentMacAddress = - pAC->Addr.Net[0].PermanentMacAddress; - pAC->Addr.Net[1].PermanentMacAddress.a[5] |= 3; - /* Set the current logical MAC address to the permanent one. */ - pAC->Addr.Net[1].CurrentMacAddress = - pAC->Addr.Net[1].PermanentMacAddress; - pAC->Addr.Net[1].CurrentMacAddressSet = SK_TRUE; - } -#endif /* SK_MAX_NETS > 1 */ - -#ifdef DEBUG - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("Permanent MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", - i, - pAC->Addr.Net[i].PermanentMacAddress.a[0], - pAC->Addr.Net[i].PermanentMacAddress.a[1], - pAC->Addr.Net[i].PermanentMacAddress.a[2], - pAC->Addr.Net[i].PermanentMacAddress.a[3], - pAC->Addr.Net[i].PermanentMacAddress.a[4], - pAC->Addr.Net[i].PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("Logical MAC Address (Net%d): %02X %02X %02X %02X %02X %02X\n", - i, - pAC->Addr.Net[i].CurrentMacAddress.a[0], - pAC->Addr.Net[i].CurrentMacAddress.a[1], - pAC->Addr.Net[i].CurrentMacAddress.a[2], - pAC->Addr.Net[i].CurrentMacAddress.a[3], - pAC->Addr.Net[i].CurrentMacAddress.a[4], - pAC->Addr.Net[i].CurrentMacAddress.a[5])) - } -#endif /* DEBUG */ - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - pAPort = &pAC->Addr.Port[i]; - - /* Read permanent port addresses from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - InAddr = (SK_U8 *) &pAPort->PermanentMacAddress.a[j]; - SK_IN8(IoC, B2_MAC_2 + 8 * i + j, InAddr); - } - - if (!pAPort->CurrentMacAddressSet) { - /* - * Set the current and previous physical MAC address - * of this port to its permanent MAC address. - */ - pAPort->CurrentMacAddress = pAPort->PermanentMacAddress; - pAPort->PreviousMacAddress = pAPort->PermanentMacAddress; - pAPort->CurrentMacAddressSet = SK_TRUE; - } - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - XM_OUTADDR(IoC, i, XM_SA, OutAddr); - } -#endif /* GENESIS */ -#ifdef YUKON - if (!pAC->GIni.GIGenesis) { - GM_OUTADDR(IoC, i, GM_SRC_ADDR_1L, OutAddr); - } -#endif /* YUKON */ -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("SkAddrInit: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->PermanentMacAddress.a[0], - pAPort->PermanentMacAddress.a[1], - pAPort->PermanentMacAddress.a[2], - pAPort->PermanentMacAddress.a[3], - pAPort->PermanentMacAddress.a[4], - pAPort->PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_INIT, - ("SkAddrInit: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->CurrentMacAddress.a[0], - pAPort->CurrentMacAddress.a[1], - pAPort->CurrentMacAddress.a[2], - pAPort->CurrentMacAddress.a[3], - pAPort->CurrentMacAddress.a[4], - pAPort->CurrentMacAddress.a[5])) -#endif /* DEBUG */ - } - /* pAC->Addr.InitDone = SK_INIT_IO; */ - break; - - case SK_INIT_RUN: -#ifdef xDEBUG - for (i = 0; i < SK_MAX_MACS; i++) { - if (pAC->Addr.Port[i].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[i] |= 16; - } - } -#endif /* DEBUG */ - - /* pAC->Addr.InitDone = SK_INIT_RUN; */ - break; - - default: /* error */ - break; - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrInit */ - -#ifndef SK_SLIM - -/****************************************************************************** - * - * SkAddrMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast table. - * - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * It calls either SkAddrXmacMcClear or SkAddrGmacMcClear, according - * to the adapter in use. The real work is done there. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int ReturnCode; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->GIni.GIGenesis) { - ReturnCode = SkAddrXmacMcClear(pAC, IoC, PortNumber, Flags); - } - else { - ReturnCode = SkAddrGmacMcClear(pAC, IoC, PortNumber, Flags); - } - - return (ReturnCode); - -} /* SkAddrMcClear */ - -#endif /* !SK_SLIM */ - -#ifndef SK_SLIM - -/****************************************************************************** - * - * SkAddrXmacMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast table - * (either entry 2 or entries 3-16 and InexactFilter) of the given port. - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrXmacMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int i; - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Clear RLMT multicast addresses. */ - pAC->Addr.Port[PortNumber].NextExactMatchRlmt = SK_ADDR_FIRST_MATCH_RLMT; - } - else { /* not permanent => DRV */ - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - - /* Clear DRV multicast addresses. */ - - pAC->Addr.Port[PortNumber].NextExactMatchDrv = SK_ADDR_FIRST_MATCH_DRV; - } - - if (!(Flags & SK_MC_SW_ONLY)) { - (void) SkAddrXmacMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrXmacMcClear */ - -#endif /* !SK_SLIM */ - -#ifndef SK_SLIM - -/****************************************************************************** - * - * SkAddrGmacMcClear - clear the multicast table - * - * Description: - * This routine clears the multicast hashing table (InexactFilter) - * (either the RLMT or the driver bits) of the given port. - * - * If not suppressed by Flag SK_MC_SW_ONLY, the hardware is updated - * immediately. - * - * Context: - * runtime, pageable - * may be called starting with SK_INIT_DATA with flag SK_MC_SW_ONLY - * may be called after SK_INIT_IO without limitation - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrGmacMcClear( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Index of affected port */ -int Flags) /* permanent/non-perm, sw-only */ -{ - int i; - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactFilter (not cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) -#endif /* DEBUG */ - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Copy DRV bits to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; - - /* Clear InexactRlmtFilter. */ - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i] = 0; - - } - } - else { /* not permanent => DRV */ - - /* Copy RLMT bits to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; - - /* Clear InexactDrvFilter. */ - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i] = 0; - } - } - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactFilter (cleared): %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[7])) -#endif /* DEBUG */ - - if (!(Flags & SK_MC_SW_ONLY)) { - (void) SkAddrGmacMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrGmacMcClear */ - -#ifndef SK_ADDR_CHEAT - -/****************************************************************************** - * - * SkXmacMcHash - hash multicast address - * - * Description: - * This routine computes the hash value for a multicast address. - * A CRC32 algorithm is used. - * - * Notes: - * The code was adapted from the XaQti data sheet. - * - * Context: - * runtime, pageable - * - * Returns: - * Hash value of multicast address. - */ -static SK_U32 SkXmacMcHash( -unsigned char *pMc) /* Multicast address */ -{ - SK_U32 Idx; - SK_U32 Bit; - SK_U32 Data; - SK_U32 Crc; - - Crc = 0xFFFFFFFFUL; - for (Idx = 0; Idx < SK_MAC_ADDR_LEN; Idx++) { - Data = *pMc++; - for (Bit = 0; Bit < 8; Bit++, Data >>= 1) { - Crc = (Crc >> 1) ^ (((Crc ^ Data) & 1) ? XMAC_POLY : 0); - } - } - - return (Crc & ((1 << HASH_BITS) - 1)); - -} /* SkXmacMcHash */ - - -/****************************************************************************** - * - * SkGmacMcHash - hash multicast address - * - * Description: - * This routine computes the hash value for a multicast address. - * A CRC16 algorithm is used. - * - * Notes: - * - * - * Context: - * runtime, pageable - * - * Returns: - * Hash value of multicast address. - */ -static SK_U32 SkGmacMcHash( -unsigned char *pMc) /* Multicast address */ -{ - SK_U32 Data; - SK_U32 TmpData; - SK_U32 Crc; - int Byte; - int Bit; - - Crc = 0xFFFFFFFFUL; - for (Byte = 0; Byte < 6; Byte++) { - /* Get next byte. */ - Data = (SK_U32) pMc[Byte]; - - /* Change bit order in byte. */ - TmpData = Data; - for (Bit = 0; Bit < 8; Bit++) { - if (TmpData & 1L) { - Data |= 1L << (7 - Bit); - } - else { - Data &= ~(1L << (7 - Bit)); - } - TmpData >>= 1; - } - - Crc ^= (Data << 24); - for (Bit = 0; Bit < 8; Bit++) { - if (Crc & 0x80000000) { - Crc = (Crc << 1) ^ GMAC_POLY; - } - else { - Crc <<= 1; - } - } - } - - return (Crc & ((1 << HASH_BITS) - 1)); - -} /* SkGmacMcHash */ - -#endif /* !SK_ADDR_CHEAT */ - -/****************************************************************************** - * - * SkAddrMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * It calls either SkAddrXmacMcAdd or SkAddrGmacMcAdd, according to the - * adapter in use. The real work is done there. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - * SK_MC_ILLEGAL_PORT - * SK_MC_RLMT_OVERFLOW - */ -int SkAddrMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int ReturnCode; - - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->GIni.GIGenesis) { - ReturnCode = SkAddrXmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); - } - else { - ReturnCode = SkAddrGmacMcAdd(pAC, IoC, PortNumber, pMc, Flags); - } - - return (ReturnCode); - -} /* SkAddrMcAdd */ - - -/****************************************************************************** - * - * SkAddrXmacMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * The multicast bit is only checked if there are no free exact match - * entries. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - * SK_MC_RLMT_OVERFLOW - */ -static int SkAddrXmacMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int i; - SK_U8 Inexact; -#ifndef SK_ADDR_CHEAT - SK_U32 HashBit; -#endif /* !defined(SK_ADDR_CHEAT) */ - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ -#ifdef xDEBUG - if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt < - SK_ADDR_FIRST_MATCH_RLMT) { - Next0[PortNumber] |= 1; - return (SK_MC_RLMT_OVERFLOW); - } -#endif /* DEBUG */ - - if (pAC->Addr.Port[PortNumber].NextExactMatchRlmt > - SK_ADDR_LAST_MATCH_RLMT) { - return (SK_MC_RLMT_OVERFLOW); - } - - /* Set a RLMT multicast address. */ - - pAC->Addr.Port[PortNumber].Exact[ - pAC->Addr.Port[PortNumber].NextExactMatchRlmt++] = *pMc; - - return (SK_MC_FILTERING_EXACT); - } - -#ifdef xDEBUG - if (pAC->Addr.Port[PortNumber].NextExactMatchDrv < - SK_ADDR_FIRST_MATCH_DRV) { - Next0[PortNumber] |= 2; - return (SK_MC_RLMT_OVERFLOW); - } -#endif /* DEBUG */ - - if (pAC->Addr.Port[PortNumber].NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) { - - /* Set exact match entry. */ - pAC->Addr.Port[PortNumber].Exact[ - pAC->Addr.Port[PortNumber].NextExactMatchDrv++] = *pMc; - - /* Clear InexactFilter */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0; - } - } - else { - if (!(pMc->a[0] & SK_MC_BIT)) { - /* Hashing only possible with multicast addresses */ - return (SK_MC_ILLEGAL_ADDRESS); - } -#ifndef SK_ADDR_CHEAT - /* Compute hash value of address. */ - HashBit = 63 - SkXmacMcHash(&pMc->a[0]); - - /* Add bit to InexactFilter. */ - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); -#else /* SK_ADDR_CHEAT */ - /* Set all bits in InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF; - } -#endif /* SK_ADDR_CHEAT */ - } - - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - - if (Inexact == 0 && pAC->Addr.Port[PortNumber].PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } - -} /* SkAddrXmacMcAdd */ - - -/****************************************************************************** - * - * SkAddrGmacMcAdd - add a multicast address to a port - * - * Description: - * This routine enables reception for a given address on the given port. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_DATA - * - * Returns: - * SK_MC_FILTERING_INEXACT - * SK_MC_ILLEGAL_ADDRESS - */ -static int SkAddrGmacMcAdd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR *pMc, /* multicast address to be added */ -int Flags) /* permanent/non-permanent */ -{ - int i; -#ifndef SK_ADDR_CHEAT - SK_U32 HashBit; -#endif /* !defined(SK_ADDR_CHEAT) */ - - if (!(pMc->a[0] & SK_MC_BIT)) { - /* Hashing only possible with multicast addresses */ - return (SK_MC_ILLEGAL_ADDRESS); - } - -#ifndef SK_ADDR_CHEAT - - /* Compute hash value of address. */ - HashBit = SkGmacMcHash(&pMc->a[0]); - - if (Flags & SK_ADDR_PERMANENT) { /* permanent => RLMT */ - - /* Add bit to InexactRlmtFilter. */ - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); - - /* Copy bit to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[i]; - } -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactRlmtFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactRlmtFilter.Bytes[7])) -#endif /* DEBUG */ - } - else { /* not permanent => DRV */ - - /* Add bit to InexactDrvFilter. */ - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[HashBit / 8] |= - 1 << (HashBit % 8); - - /* Copy bit to InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] |= - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[i]; - } -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("GMAC InexactDrvFilter: %02X %02X %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[0], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[1], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[2], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[3], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[4], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[5], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[6], - pAC->Addr.Port[PortNumber].InexactDrvFilter.Bytes[7])) -#endif /* DEBUG */ - } - -#else /* SK_ADDR_CHEAT */ - - /* Set all bits in InexactFilter. */ - for (i = 0; i < 8; i++) { - pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i] = 0xFF; - } -#endif /* SK_ADDR_CHEAT */ - - return (SK_MC_FILTERING_INEXACT); - -} /* SkAddrGmacMcAdd */ - -#endif /* !SK_SLIM */ - -/****************************************************************************** - * - * SkAddrMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * It calls either SkAddrXmacMcUpdate or SkAddrGmacMcUpdate, according - * to the adapter in use. The real work is done there. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ - int ReturnCode = 0; -#if (!defined(SK_SLIM) || defined(DEBUG)) - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } -#endif /* !SK_SLIM || DEBUG */ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - ReturnCode = SkAddrXmacMcUpdate(pAC, IoC, PortNumber); - } -#endif /* GENESIS */ -#ifdef YUKON - if (!pAC->GIni.GIGenesis) { - ReturnCode = SkAddrGmacMcUpdate(pAC, IoC, PortNumber); - } -#endif /* YUKON */ - return (ReturnCode); - -} /* SkAddrMcUpdate */ - - -#ifdef GENESIS - -/****************************************************************************** - * - * SkAddrXmacMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrXmacMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ - SK_U32 i; - SK_U8 Inexact; - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrXmacMcUpdate on Port %u.\n", PortNumber)) - - pAPort = &pAC->Addr.Port[PortNumber]; - -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) -#endif /* DEBUG */ - - /* Start with 0 to also program the logical MAC address. */ - for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { - /* Set exact match address i on XMAC */ - OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0]; - XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr); - } - - /* Clear other permanent exact match addresses on XMAC */ - if (pAPort->NextExactMatchRlmt <= SK_ADDR_LAST_MATCH_RLMT) { - - SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchRlmt, - SK_ADDR_LAST_MATCH_RLMT); - } - - for (i = pAPort->FirstExactMatchDrv; i < pAPort->NextExactMatchDrv; i++) { - OutAddr = (SK_U16 *) &pAPort->Exact[i].a[0]; - XM_OUTADDR(IoC, PortNumber, XM_EXM(i), OutAddr); - } - - /* Clear other non-permanent exact match addresses on XMAC */ - if (pAPort->NextExactMatchDrv <= SK_ADDR_LAST_MATCH_DRV) { - - SkXmClrExactAddr(pAC, IoC, PortNumber, pAPort->NextExactMatchDrv, - SK_ADDR_LAST_MATCH_DRV); - } - - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAPort->InexactFilter.Bytes[i]; - } - - if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) { - - /* Set all bits in 64-bit hash register. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else if (Inexact != 0) { - - /* Set 64-bit hash register to InexactFilter. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &pAPort->InexactFilter.Bytes[0]); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else { - /* Disable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE); - } - - if (pAPort->PromMode != SK_PROM_MODE_NONE) { - (void) SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); - } - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; - - XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); - -#ifdef xDEBUG - for (i = 0; i < pAPort->NextExactMatchRlmt; i++) { - SK_U8 InAddr8[6]; - SK_U16 *InAddr; - - /* Get exact match address i from port PortNumber. */ - InAddr = (SK_U16 *) &InAddr8[0]; - - XM_INADDR(IoC, PortNumber, XM_EXM(i), InAddr); - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrXmacMcUpdate: MC address %d on Port %u: ", - "%02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x\n", - i, - PortNumber, - InAddr8[0], - InAddr8[1], - InAddr8[2], - InAddr8[3], - InAddr8[4], - InAddr8[5], - pAPort->Exact[i].a[0], - pAPort->Exact[i].a[1], - pAPort->Exact[i].a[2], - pAPort->Exact[i].a[3], - pAPort->Exact[i].a[4], - pAPort->Exact[i].a[5])) - } -#endif /* DEBUG */ - - /* Determine return value. */ - if (Inexact == 0 && pAPort->PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } - -} /* SkAddrXmacMcUpdate */ - -#endif /* GENESIS */ - -#ifdef YUKON - -/****************************************************************************** - * - * SkAddrGmacMcUpdate - update the HW MC address table and set the MAC address - * - * Description: - * This routine enables reception of the addresses contained in a local - * table for a given port. - * It also programs the port's current physical MAC address. - * - * Notes: - * The return code is only valid for SK_PROM_MODE_NONE. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_MC_FILTERING_EXACT - * SK_MC_FILTERING_INEXACT - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrGmacMcUpdate( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber) /* Port Number */ -{ -#ifndef SK_SLIM - SK_U32 i; - SK_U8 Inexact; -#endif /* not SK_SLIM */ - SK_U16 *OutAddr; - SK_ADDR_PORT *pAPort; - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate on Port %u.\n", PortNumber)) - - pAPort = &pAC->Addr.Port[PortNumber]; - -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("Next0 on Port %d: %d\n", PortNumber, Next0[PortNumber])) -#endif /* DEBUG */ - -#ifndef SK_SLIM - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAPort->InexactFilter.Bytes[i]; - } - - /* Set 64-bit hash register to InexactFilter. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, - &pAPort->InexactFilter.Bytes[0]); - - if (pAPort->PromMode & SK_PROM_MODE_ALL_MC) { - - /* Set all bits in 64-bit hash register. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else { - /* Enable Hashing. */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - - if (pAPort->PromMode != SK_PROM_MODE_NONE) { - (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); - } -#else /* SK_SLIM */ - - /* Set all bits in 64-bit hash register. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - - (void) SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, pAPort->PromMode); - -#endif /* SK_SLIM */ - - /* Set port's current physical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->CurrentMacAddress.a[0]; - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); - - /* Set port's current logical MAC address. */ - OutAddr = (SK_U16 *) &pAPort->Exact[0].a[0]; - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_2L, OutAddr); - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate: Permanent Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->Exact[0].a[0], - pAPort->Exact[0].a[1], - pAPort->Exact[0].a[2], - pAPort->Exact[0].a[3], - pAPort->Exact[0].a[4], - pAPort->Exact[0].a[5])) - - SK_DBG_MSG(pAC, SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrGmacMcUpdate: Physical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAPort->CurrentMacAddress.a[0], - pAPort->CurrentMacAddress.a[1], - pAPort->CurrentMacAddress.a[2], - pAPort->CurrentMacAddress.a[3], - pAPort->CurrentMacAddress.a[4], - pAPort->CurrentMacAddress.a[5])) -#endif /* DEBUG */ - -#ifndef SK_SLIM - /* Determine return value. */ - if (Inexact == 0 && pAPort->PromMode == 0) { - return (SK_MC_FILTERING_EXACT); - } - else { - return (SK_MC_FILTERING_INEXACT); - } -#else /* SK_SLIM */ - return (SK_MC_FILTERING_INEXACT); -#endif /* SK_SLIM */ - -} /* SkAddrGmacMcUpdate */ - -#endif /* YUKON */ - -#ifndef SK_NO_MAO - -/****************************************************************************** - * - * SkAddrOverride - override a port's MAC address - * - * Description: - * This routine overrides the MAC address of one port. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS if successful. - * SK_ADDR_DUPLICATE_ADDRESS if duplicate MAC address. - * SK_ADDR_MULTICAST_ADDRESS if multicast or broadcast address. - * SK_ADDR_TOO_EARLY if SK_INIT_IO was not executed before. - */ -int SkAddrOverride( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* Port Number */ -SK_MAC_ADDR SK_FAR *pNewAddr, /* new MAC address */ -int Flags) /* logical/physical MAC address */ -{ -#ifndef SK_NO_RLMT - SK_EVPARA Para; -#endif /* !SK_NO_RLMT */ - SK_U32 NetNumber; - SK_U32 i; - SK_U16 SK_FAR *OutAddr; - -#ifndef SK_NO_RLMT - NetNumber = pAC->Rlmt.Port[PortNumber].Net->NetNumber; -#else - NetNumber = 0; -#endif /* SK_NO_RLMT */ -#if (!defined(SK_SLIM) || defined(DEBUG)) - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } -#endif /* !SK_SLIM || DEBUG */ - if (pNewAddr != NULL && (pNewAddr->a[0] & SK_MC_BIT) != 0) { - return (SK_ADDR_MULTICAST_ADDRESS); - } - - if (!pAC->Addr.Net[NetNumber].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (Flags & SK_ADDR_SET_LOGICAL) { /* Activate logical MAC address. */ - /* Parameter *pNewAddr is ignored. */ - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - } -#ifndef SK_NO_RLMT - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; -#endif /* !SK_NO_RLMT */ - pAC->Addr.Port[PortNumber].Exact[0] = - pAC->Addr.Net[NetNumber].CurrentMacAddress; - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - else if (Flags & SK_ADDR_CLEAR_LOGICAL) { - /* Deactivate logical MAC address. */ - /* Parameter *pNewAddr is ignored. */ - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - } -#ifndef SK_NO_RLMT - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; -#endif /* !SK_NO_RLMT */ - for (i = 0; i < SK_MAC_ADDR_LEN; i++ ) { - pAC->Addr.Port[PortNumber].Exact[0].a[i] = 0; - } - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - else if (Flags & SK_ADDR_PHYSICAL_ADDRESS) { /* Physical MAC address. */ - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Port[i].CurrentMacAddress.a)) { - if (i == PortNumber) { - return (SK_ADDR_SUCCESS); - } - else { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - } - } - - pAC->Addr.Port[PortNumber].PreviousMacAddress = - pAC->Addr.Port[PortNumber].CurrentMacAddress; - pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; - - /* Change port's physical MAC address. */ - OutAddr = (SK_U16 SK_FAR *) pNewAddr; -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - XM_OUTADDR(IoC, PortNumber, XM_SA, OutAddr); - } -#endif /* GENESIS */ -#ifdef YUKON - if (!pAC->GIni.GIGenesis) { - GM_OUTADDR(IoC, PortNumber, GM_SRC_ADDR_1L, OutAddr); - } -#endif /* YUKON */ - -#ifndef SK_NO_RLMT - /* Report address change to RLMT. */ - Para.Para32[0] = PortNumber; - Para.Para32[0] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); -#endif /* !SK_NO_RLMT */ - } - else { /* Logical MAC address. */ - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Net[NetNumber].CurrentMacAddress.a)) { - return (SK_ADDR_SUCCESS); - } - - for (i = 0; i < (SK_U32) pAC->GIni.GIMacsFound; i++) { - if (!pAC->Addr.Port[i].CurrentMacAddressSet) { - return (SK_ADDR_TOO_EARLY); - } - - if (SK_ADDR_EQUAL(pNewAddr->a, - pAC->Addr.Port[i].CurrentMacAddress.a)) { - return (SK_ADDR_DUPLICATE_ADDRESS); - } - } - - /* - * In case that the physical and the logical MAC addresses are equal - * we must also change the physical MAC address here. - * In this case we have an adapter which initially was programmed with - * two identical MAC addresses. - */ - if (SK_ADDR_EQUAL(pAC->Addr.Port[PortNumber].CurrentMacAddress.a, - pAC->Addr.Port[PortNumber].Exact[0].a)) { - - pAC->Addr.Port[PortNumber].PreviousMacAddress = - pAC->Addr.Port[PortNumber].CurrentMacAddress; - pAC->Addr.Port[PortNumber].CurrentMacAddress = *pNewAddr; - -#ifndef SK_NO_RLMT - /* Report address change to RLMT. */ - Para.Para32[0] = PortNumber; - Para.Para32[0] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_PORT_ADDR, Para); -#endif /* !SK_NO_RLMT */ - } - -#ifndef SK_NO_RLMT - /* Set PortNumber to number of net's active port. */ - PortNumber = pAC->Rlmt.Net[NetNumber]. - Port[pAC->Addr.Net[NetNumber].ActivePort]->PortNumber; -#endif /* !SK_NO_RLMT */ - pAC->Addr.Net[NetNumber].CurrentMacAddress = *pNewAddr; - pAC->Addr.Port[PortNumber].Exact[0] = *pNewAddr; -#ifdef DEBUG - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrOverride: Permanent MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[0], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[1], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[2], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[3], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[4], - pAC->Addr.Net[NetNumber].PermanentMacAddress.a[5])) - - SK_DBG_MSG(pAC,SK_DBGMOD_ADDR, SK_DBGCAT_CTRL, - ("SkAddrOverride: New logical MAC Address: %02X %02X %02X %02X %02X %02X\n", - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[0], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[1], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[2], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[3], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[4], - pAC->Addr.Net[NetNumber].CurrentMacAddress.a[5])) -#endif /* DEBUG */ - - /* Write address to first exact match entry of active port. */ - (void) SkAddrMcUpdate(pAC, IoC, PortNumber); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrOverride */ - - -#endif /* SK_NO_MAO */ - -/****************************************************************************** - * - * SkAddrPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * It calls either SkAddrXmacPromiscuousChange or - * SkAddrGmacPromiscuousChange, according to the adapter in use. - * The real work is done there. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - int ReturnCode = 0; -#if (!defined(SK_SLIM) || defined(DEBUG)) - if (PortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } -#endif /* !SK_SLIM || DEBUG */ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - ReturnCode = - SkAddrXmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); - } -#endif /* GENESIS */ -#ifdef YUKON - if (!pAC->GIni.GIGenesis) { - ReturnCode = - SkAddrGmacPromiscuousChange(pAC, IoC, PortNumber, NewPromMode); - } -#endif /* YUKON */ - - return (ReturnCode); - -} /* SkAddrPromiscuousChange */ - -#ifdef GENESIS - -/****************************************************************************** - * - * SkAddrXmacPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrXmacPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - int i; - SK_BOOL InexactModeBit; - SK_U8 Inexact; - SK_U8 HwInexact; - SK_FILTER64 HwInexactFilter; - SK_U16 LoMode; /* Lower 16 bits of XMAC Mode Register. */ - int CurPromMode = SK_PROM_MODE_NONE; - - /* Read CurPromMode from Hardware. */ - XM_IN16(IoC, PortNumber, XM_MODE, &LoMode); - - if ((LoMode & XM_MD_ENA_PROM) != 0) { - /* Promiscuous mode! */ - CurPromMode |= SK_PROM_MODE_LLC; - } - - for (Inexact = 0xFF, i = 0; i < 8; i++) { - Inexact &= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - if (Inexact == 0xFF) { - CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); - } - else { - /* Get InexactModeBit (bit XM_MD_ENA_HASH in mode register) */ - XM_IN16(IoC, PortNumber, XM_MODE, &LoMode); - - InexactModeBit = (LoMode & XM_MD_ENA_HASH) != 0; - - /* Read 64-bit hash register from XMAC */ - XM_INHASH(IoC, PortNumber, XM_HSM, &HwInexactFilter.Bytes[0]); - - for (HwInexact = 0xFF, i = 0; i < 8; i++) { - HwInexact &= HwInexactFilter.Bytes[i]; - } - - if (InexactModeBit && (HwInexact == 0xFF)) { - CurPromMode |= SK_PROM_MODE_ALL_MC; - } - } - - pAC->Addr.Port[PortNumber].PromMode = NewPromMode; - - if (NewPromMode == CurPromMode) { - return (SK_ADDR_SUCCESS); - } - - if ((NewPromMode & SK_PROM_MODE_ALL_MC) && - !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC. */ - - /* Set all bits in 64-bit hash register. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_ALL_MC) && - !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm MC. */ - for (Inexact = 0, i = 0; i < 8; i++) { - Inexact |= pAC->Addr.Port[PortNumber].InexactFilter.Bytes[i]; - } - if (Inexact == 0) { - /* Disable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_FALSE); - } - else { - /* Set 64-bit hash register to InexactFilter. */ - XM_OUTHASH(IoC, PortNumber, XM_HSM, - &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - } - - if ((NewPromMode & SK_PROM_MODE_LLC) && - !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ - /* Set the MAC in Promiscuous Mode */ - SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_LLC) && - !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC. */ - /* Clear Promiscuous Mode */ - SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrXmacPromiscuousChange */ - -#endif /* GENESIS */ - -#ifdef YUKON - -/****************************************************************************** - * - * SkAddrGmacPromiscuousChange - set promiscuous mode for given port - * - * Description: - * This routine manages promiscuous mode: - * - none - * - all LLC frames - * - all MC frames - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -static int SkAddrGmacPromiscuousChange( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 PortNumber, /* port whose promiscuous mode changes */ -int NewPromMode) /* new promiscuous mode */ -{ - SK_U16 ReceiveControl; /* GMAC Receive Control Register */ - int CurPromMode = SK_PROM_MODE_NONE; - - /* Read CurPromMode from Hardware. */ - GM_IN16(IoC, PortNumber, GM_RX_CTRL, &ReceiveControl); - - if ((ReceiveControl & (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)) == 0) { - /* Promiscuous mode! */ - CurPromMode |= SK_PROM_MODE_LLC; - } - - if ((ReceiveControl & GM_RXCR_MCF_ENA) == 0) { - /* All Multicast mode! */ - CurPromMode |= (pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_ALL_MC); - } - - pAC->Addr.Port[PortNumber].PromMode = NewPromMode; - - if (NewPromMode == CurPromMode) { - return (SK_ADDR_SUCCESS); - } - - if ((NewPromMode & SK_PROM_MODE_ALL_MC) && - !(CurPromMode & SK_PROM_MODE_ALL_MC)) { /* All MC */ - - /* Set all bits in 64-bit hash register. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, &OnesHash); - - /* Enable Hashing */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - - if ((CurPromMode & SK_PROM_MODE_ALL_MC) && - !(NewPromMode & SK_PROM_MODE_ALL_MC)) { /* Norm. MC */ - - /* Set 64-bit hash register to InexactFilter. */ - GM_OUTHASH(IoC, PortNumber, GM_MC_ADDR_H1, - &pAC->Addr.Port[PortNumber].InexactFilter.Bytes[0]); - - /* Enable Hashing. */ - SkMacHashing(pAC, IoC, (int) PortNumber, SK_TRUE); - } - - if ((NewPromMode & SK_PROM_MODE_LLC) && - !(CurPromMode & SK_PROM_MODE_LLC)) { /* Prom. LLC */ - - /* Set the MAC to Promiscuous Mode. */ - SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_TRUE); - } - else if ((CurPromMode & SK_PROM_MODE_LLC) && - !(NewPromMode & SK_PROM_MODE_LLC)) { /* Norm. LLC */ - - /* Clear Promiscuous Mode. */ - SkMacPromiscMode(pAC, IoC, (int) PortNumber, SK_FALSE); - } - - return (SK_ADDR_SUCCESS); - -} /* SkAddrGmacPromiscuousChange */ - -#endif /* YUKON */ - -#ifndef SK_SLIM - -/****************************************************************************** - * - * SkAddrSwap - swap address info - * - * Description: - * This routine swaps address info of two ports. - * - * Context: - * runtime, pageable - * may be called after SK_INIT_IO - * - * Returns: - * SK_ADDR_SUCCESS - * SK_ADDR_ILLEGAL_PORT - */ -int SkAddrSwap( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -SK_U32 FromPortNumber, /* Port1 Index */ -SK_U32 ToPortNumber) /* Port2 Index */ -{ - int i; - SK_U8 Byte; - SK_MAC_ADDR MacAddr; - SK_U32 DWord; - - if (FromPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (ToPortNumber >= (SK_U32) pAC->GIni.GIMacsFound) { - return (SK_ADDR_ILLEGAL_PORT); - } - - if (pAC->Rlmt.Port[FromPortNumber].Net != pAC->Rlmt.Port[ToPortNumber].Net) { - return (SK_ADDR_ILLEGAL_PORT); - } - - /* - * Swap: - * - Exact Match Entries (GEnesis and Yukon) - * Yukon uses first entry for the logical MAC - * address (stored in the second GMAC register). - * - FirstExactMatchRlmt (GEnesis only) - * - NextExactMatchRlmt (GEnesis only) - * - FirstExactMatchDrv (GEnesis only) - * - NextExactMatchDrv (GEnesis only) - * - 64-bit filter (InexactFilter) - * - Promiscuous Mode - * of ports. - */ - - for (i = 0; i < SK_ADDR_EXACT_MATCHES; i++) { - MacAddr = pAC->Addr.Port[FromPortNumber].Exact[i]; - pAC->Addr.Port[FromPortNumber].Exact[i] = - pAC->Addr.Port[ToPortNumber].Exact[i]; - pAC->Addr.Port[ToPortNumber].Exact[i] = MacAddr; - } - - for (i = 0; i < 8; i++) { - Byte = pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i]; - pAC->Addr.Port[FromPortNumber].InexactFilter.Bytes[i] = - pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i]; - pAC->Addr.Port[ToPortNumber].InexactFilter.Bytes[i] = Byte; - } - - i = pAC->Addr.Port[FromPortNumber].PromMode; - pAC->Addr.Port[FromPortNumber].PromMode = pAC->Addr.Port[ToPortNumber].PromMode; - pAC->Addr.Port[ToPortNumber].PromMode = i; - - if (pAC->GIni.GIGenesis) { - DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt; - pAC->Addr.Port[FromPortNumber].FirstExactMatchRlmt = - pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt; - pAC->Addr.Port[ToPortNumber].FirstExactMatchRlmt = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt; - pAC->Addr.Port[FromPortNumber].NextExactMatchRlmt = - pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt; - pAC->Addr.Port[ToPortNumber].NextExactMatchRlmt = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv; - pAC->Addr.Port[FromPortNumber].FirstExactMatchDrv = - pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv; - pAC->Addr.Port[ToPortNumber].FirstExactMatchDrv = DWord; - - DWord = pAC->Addr.Port[FromPortNumber].NextExactMatchDrv; - pAC->Addr.Port[FromPortNumber].NextExactMatchDrv = - pAC->Addr.Port[ToPortNumber].NextExactMatchDrv; - pAC->Addr.Port[ToPortNumber].NextExactMatchDrv = DWord; - } - - /* CAUTION: Solution works if only ports of one adapter are in use. */ - for (i = 0; (SK_U32) i < pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber]. - Net->NetNumber].NumPorts; i++) { - if (pAC->Rlmt.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber]. - Port[i]->PortNumber == ToPortNumber) { - pAC->Addr.Net[pAC->Rlmt.Port[ToPortNumber].Net->NetNumber]. - ActivePort = i; - /* 20001207 RA: Was "ToPortNumber;". */ - } - } - - (void) SkAddrMcUpdate(pAC, IoC, FromPortNumber); - (void) SkAddrMcUpdate(pAC, IoC, ToPortNumber); - - return (SK_ADDR_SUCCESS); - -} /* SkAddrSwap */ - -#endif /* !SK_SLIM */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - diff --git a/drivers/net/sk98lin/skdim.c b/drivers/net/sk98lin/skdim.c deleted file mode 100644 index 37ce03fb8de3..000000000000 --- a/drivers/net/sk98lin/skdim.c +++ /dev/null @@ -1,742 +0,0 @@ -/****************************************************************************** - * - * Name: skdim.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.5 $ - * Date: $Date: 2003/11/28 12:55:40 $ - * Purpose: All functions to maintain interrupt moderation - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module is intended to manage the dynamic interrupt moderation on both - * GEnesis and Yukon adapters. - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef lint -static const char SysKonnectFileId[] = - "@(#) $Id: skdim.c,v 1.5 2003/11/28 12:55:40 rroesler Exp $ (C) SysKonnect."; -#endif - -#define __SKADDR_C - -#ifdef __cplusplus -#error C++ is not yet supported. -extern "C" { -#endif - -/******************************************************************************* -** -** Includes -** -*******************************************************************************/ - -#ifndef __INC_SKDRV1ST_H -#include "h/skdrv1st.h" -#endif - -#ifndef __INC_SKDRV2ND_H -#include "h/skdrv2nd.h" -#endif - -#include - -/******************************************************************************* -** -** Defines -** -*******************************************************************************/ - -/******************************************************************************* -** -** Typedefs -** -*******************************************************************************/ - -/******************************************************************************* -** -** Local function prototypes -** -*******************************************************************************/ - -static unsigned int GetCurrentSystemLoad(SK_AC *pAC); -static SK_U64 GetIsrCalls(SK_AC *pAC); -static SK_BOOL IsIntModEnabled(SK_AC *pAC); -static void SetCurrIntCtr(SK_AC *pAC); -static void EnableIntMod(SK_AC *pAC); -static void DisableIntMod(SK_AC *pAC); -static void ResizeDimTimerDuration(SK_AC *pAC); -static void DisplaySelectedModerationType(SK_AC *pAC); -static void DisplaySelectedModerationMask(SK_AC *pAC); -static void DisplayDescrRatio(SK_AC *pAC); - -/******************************************************************************* -** -** Global variables -** -*******************************************************************************/ - -/******************************************************************************* -** -** Local variables -** -*******************************************************************************/ - -/******************************************************************************* -** -** Global functions -** -*******************************************************************************/ - -/******************************************************************************* -** Function : SkDimModerate -** Description : Called in every ISR to check if moderation is to be applied -** or not for the current number of interrupts -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : void (!) -** Notes : - -*******************************************************************************/ - -void -SkDimModerate(SK_AC *pAC) { - unsigned int CurrSysLoad = 0; /* expressed in percent */ - unsigned int LoadIncrease = 0; /* expressed in percent */ - SK_U64 ThresholdInts = 0; - SK_U64 IsrCallsPerSec = 0; - -#define M_DIMINFO pAC->DynIrqModInfo - - if (!IsIntModEnabled(pAC)) { - if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { - CurrSysLoad = GetCurrentSystemLoad(pAC); - if (CurrSysLoad > 75) { - /* - ** More than 75% total system load! Enable the moderation - ** to shield the system against too many interrupts. - */ - EnableIntMod(pAC); - } else if (CurrSysLoad > M_DIMINFO.PrevSysLoad) { - LoadIncrease = (CurrSysLoad - M_DIMINFO.PrevSysLoad); - if (LoadIncrease > ((M_DIMINFO.PrevSysLoad * - C_INT_MOD_ENABLE_PERCENTAGE) / 100)) { - if (CurrSysLoad > 10) { - /* - ** More than 50% increase with respect to the - ** previous load of the system. Most likely this - ** is due to our ISR-proc... - */ - EnableIntMod(pAC); - } - } - } else { - /* - ** Neither too much system load at all nor too much increase - ** with respect to the previous system load. Hence, we can leave - ** the ISR-handling like it is without enabling moderation. - */ - } - M_DIMINFO.PrevSysLoad = CurrSysLoad; - } - } else { - if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { - ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec * - C_INT_MOD_DISABLE_PERCENTAGE) / 100); - IsrCallsPerSec = GetIsrCalls(pAC); - if (IsrCallsPerSec <= ThresholdInts) { - /* - ** The number of interrupts within the last second is - ** lower than the disable_percentage of the desried - ** maxrate. Therefore we can disable the moderation. - */ - DisableIntMod(pAC); - M_DIMINFO.MaxModIntsPerSec = - (M_DIMINFO.MaxModIntsPerSecUpperLimit + - M_DIMINFO.MaxModIntsPerSecLowerLimit) / 2; - } else { - /* - ** The number of interrupts per sec is the same as expected. - ** Evalulate the descriptor-ratio. If it has changed, a resize - ** in the moderation timer might be useful - */ - if (M_DIMINFO.AutoSizing) { - ResizeDimTimerDuration(pAC); - } - } - } - } - - /* - ** Some information to the log... - */ - if (M_DIMINFO.DisplayStats) { - DisplaySelectedModerationType(pAC); - DisplaySelectedModerationMask(pAC); - DisplayDescrRatio(pAC); - } - - M_DIMINFO.NbrProcessedDescr = 0; - SetCurrIntCtr(pAC); -} - -/******************************************************************************* -** Function : SkDimStartModerationTimer -** Description : Starts the audit-timer for the dynamic interrupt moderation -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : void (!) -** Notes : - -*******************************************************************************/ - -void -SkDimStartModerationTimer(SK_AC *pAC) { - SK_EVPARA EventParam; /* Event struct for timer event */ - - SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = SK_DRV_MODERATION_TIMER; - SkTimerStart(pAC, pAC->IoBase, &pAC->DynIrqModInfo.ModTimer, - SK_DRV_MODERATION_TIMER_LENGTH, - SKGE_DRV, SK_DRV_TIMER, EventParam); -} - -/******************************************************************************* -** Function : SkDimEnableModerationIfNeeded -** Description : Either enables or disables moderation -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : void (!) -** Notes : This function is called when a particular adapter is opened -** There is no Disable function, because when all interrupts -** might be disable, the moderation timer has no meaning at all -******************************************************************************/ - -void -SkDimEnableModerationIfNeeded(SK_AC *pAC) { - - if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_STATIC) { - EnableIntMod(pAC); /* notification print in this function */ - } else if (M_DIMINFO.IntModTypeSelect == C_INT_MOD_DYNAMIC) { - SkDimStartModerationTimer(pAC); - if (M_DIMINFO.DisplayStats) { - printk("Dynamic moderation has been enabled\n"); - } - } else { - if (M_DIMINFO.DisplayStats) { - printk("No moderation has been enabled\n"); - } - } -} - -/******************************************************************************* -** Function : SkDimDisplayModerationSettings -** Description : Displays the current settings regarding interrupt moderation -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : void (!) -** Notes : - -*******************************************************************************/ - -void -SkDimDisplayModerationSettings(SK_AC *pAC) { - DisplaySelectedModerationType(pAC); - DisplaySelectedModerationMask(pAC); -} - -/******************************************************************************* -** -** Local functions -** -*******************************************************************************/ - -/******************************************************************************* -** Function : GetCurrentSystemLoad -** Description : Retrieves the current system load of the system. This load -** is evaluated for all processors within the system. -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : unsigned int: load expressed in percentage -** Notes : The possible range being returned is from 0 up to 100. -** Whereas 0 means 'no load at all' and 100 'system fully loaded' -** It is impossible to determine what actually causes the system -** to be in 100%, but maybe that is due to too much interrupts. -*******************************************************************************/ - -static unsigned int -GetCurrentSystemLoad(SK_AC *pAC) { - unsigned long jif = jiffies; - unsigned int UserTime = 0; - unsigned int SystemTime = 0; - unsigned int NiceTime = 0; - unsigned int IdleTime = 0; - unsigned int TotalTime = 0; - unsigned int UsedTime = 0; - unsigned int SystemLoad = 0; - - /* unsigned int NbrCpu = 0; */ - - /* - ** The following lines have been commented out, because - ** from kernel 2.5.44 onwards, the kernel-owned structure - ** - ** struct kernel_stat kstat - ** - ** is not marked as an exported symbol in the file - ** - ** kernel/ksyms.c - ** - ** As a consequence, using this driver as KLM is not possible - ** and any access of the structure kernel_stat via the - ** dedicated macros kstat_cpu(i).cpustat.xxx is to be avoided. - ** - ** The kstat-information might be added again in future - ** versions of the 2.5.xx kernel, but for the time being, - ** number of interrupts will serve as indication how much - ** load we currently have... - ** - ** for (NbrCpu = 0; NbrCpu < num_online_cpus(); NbrCpu++) { - ** UserTime = UserTime + kstat_cpu(NbrCpu).cpustat.user; - ** NiceTime = NiceTime + kstat_cpu(NbrCpu).cpustat.nice; - ** SystemTime = SystemTime + kstat_cpu(NbrCpu).cpustat.system; - ** } - */ - SK_U64 ThresholdInts = 0; - SK_U64 IsrCallsPerSec = 0; - - ThresholdInts = ((M_DIMINFO.MaxModIntsPerSec * - C_INT_MOD_ENABLE_PERCENTAGE) + 100); - IsrCallsPerSec = GetIsrCalls(pAC); - if (IsrCallsPerSec >= ThresholdInts) { - /* - ** We do not know how much the real CPU-load is! - ** Return 80% as a default in order to activate DIM - */ - SystemLoad = 80; - return (SystemLoad); - } - - UsedTime = UserTime + NiceTime + SystemTime; - - IdleTime = jif * num_online_cpus() - UsedTime; - TotalTime = UsedTime + IdleTime; - - SystemLoad = ( 100 * (UsedTime - M_DIMINFO.PrevUsedTime) ) / - (TotalTime - M_DIMINFO.PrevTotalTime); - - if (M_DIMINFO.DisplayStats) { - printk("Current system load is: %u\n", SystemLoad); - } - - M_DIMINFO.PrevTotalTime = TotalTime; - M_DIMINFO.PrevUsedTime = UsedTime; - - return (SystemLoad); -} - -/******************************************************************************* -** Function : GetIsrCalls -** Description : Depending on the selected moderation mask, this function will -** return the number of interrupts handled in the previous time- -** frame. This evaluated number is based on the current number -** of interrupts stored in PNMI-context and the previous stored -** interrupts. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : int: the number of interrupts being executed in the last -** timeframe -** Notes : It makes only sense to call this function, when dynamic -** interrupt moderation is applied -*******************************************************************************/ - -static SK_U64 -GetIsrCalls(SK_AC *pAC) { - SK_U64 RxPort0IntDiff = 0; - SK_U64 RxPort1IntDiff = 0; - SK_U64 TxPort0IntDiff = 0; - SK_U64 TxPort1IntDiff = 0; - - if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_TX_ONLY) { - if (pAC->GIni.GIMacsFound == 2) { - TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - - pAC->DynIrqModInfo.PrevPort1TxIntrCts; - } - TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - - pAC->DynIrqModInfo.PrevPort0TxIntrCts; - } else if (pAC->DynIrqModInfo.MaskIrqModeration == IRQ_MASK_RX_ONLY) { - if (pAC->GIni.GIMacsFound == 2) { - RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - - pAC->DynIrqModInfo.PrevPort1RxIntrCts; - } - RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - - pAC->DynIrqModInfo.PrevPort0RxIntrCts; - } else { - if (pAC->GIni.GIMacsFound == 2) { - RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - - pAC->DynIrqModInfo.PrevPort1RxIntrCts; - TxPort1IntDiff = pAC->Pnmi.Port[1].TxIntrCts - - pAC->DynIrqModInfo.PrevPort1TxIntrCts; - } - RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - - pAC->DynIrqModInfo.PrevPort0RxIntrCts; - TxPort0IntDiff = pAC->Pnmi.Port[0].TxIntrCts - - pAC->DynIrqModInfo.PrevPort0TxIntrCts; - } - - return (RxPort0IntDiff + RxPort1IntDiff + TxPort0IntDiff + TxPort1IntDiff); -} - -/******************************************************************************* -** Function : GetRxCalls -** Description : This function will return the number of times a receive inter- -** rupt was processed. This is needed to evaluate any resizing -** factor. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : SK_U64: the number of RX-ints being processed -** Notes : It makes only sense to call this function, when dynamic -** interrupt moderation is applied -*******************************************************************************/ - -static SK_U64 -GetRxCalls(SK_AC *pAC) { - SK_U64 RxPort0IntDiff = 0; - SK_U64 RxPort1IntDiff = 0; - - if (pAC->GIni.GIMacsFound == 2) { - RxPort1IntDiff = pAC->Pnmi.Port[1].RxIntrCts - - pAC->DynIrqModInfo.PrevPort1RxIntrCts; - } - RxPort0IntDiff = pAC->Pnmi.Port[0].RxIntrCts - - pAC->DynIrqModInfo.PrevPort0RxIntrCts; - - return (RxPort0IntDiff + RxPort1IntDiff); -} - -/******************************************************************************* -** Function : SetCurrIntCtr -** Description : Will store the current number orf occured interrupts in the -** adapter context. This is needed to evaluated the number of -** interrupts within a current timeframe. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : void (!) -** Notes : - -*******************************************************************************/ - -static void -SetCurrIntCtr(SK_AC *pAC) { - if (pAC->GIni.GIMacsFound == 2) { - pAC->DynIrqModInfo.PrevPort1RxIntrCts = pAC->Pnmi.Port[1].RxIntrCts; - pAC->DynIrqModInfo.PrevPort1TxIntrCts = pAC->Pnmi.Port[1].TxIntrCts; - } - pAC->DynIrqModInfo.PrevPort0RxIntrCts = pAC->Pnmi.Port[0].RxIntrCts; - pAC->DynIrqModInfo.PrevPort0TxIntrCts = pAC->Pnmi.Port[0].TxIntrCts; -} - -/******************************************************************************* -** Function : IsIntModEnabled() -** Description : Retrieves the current value of the interrupts moderation -** command register. Its content determines whether any -** moderation is running or not. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : SK_TRUE : if mod timer running -** SK_FALSE : if no moderation is being performed -** Notes : - -*******************************************************************************/ - -static SK_BOOL -IsIntModEnabled(SK_AC *pAC) { - unsigned long CtrCmd; - - SK_IN32(pAC->IoBase, B2_IRQM_CTRL, &CtrCmd); - if ((CtrCmd & TIM_START) == TIM_START) { - return SK_TRUE; - } else { - return SK_FALSE; - } -} - -/******************************************************************************* -** Function : EnableIntMod() -** Description : Enables the interrupt moderation using the values stored in -** in the pAC->DynIntMod data structure -** Programmer : Ralph Roesler -** Last Modified: 22-mar-03 -** Returns : - -** Notes : - -*******************************************************************************/ - -static void -EnableIntMod(SK_AC *pAC) { - unsigned long ModBase; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec; - } else { - ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec; - } - - SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); - SK_OUT32(pAC->IoBase, B2_IRQM_MSK, pAC->DynIrqModInfo.MaskIrqModeration); - SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_START); - if (M_DIMINFO.DisplayStats) { - printk("Enabled interrupt moderation (%i ints/sec)\n", - M_DIMINFO.MaxModIntsPerSec); - } -} - -/******************************************************************************* -** Function : DisableIntMod() -** Description : Disables the interrupt moderation independent of what inter- -** rupts are running or not -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : - -** Notes : - -*******************************************************************************/ - -static void -DisableIntMod(SK_AC *pAC) { - - SK_OUT32(pAC->IoBase, B2_IRQM_CTRL, TIM_STOP); - if (M_DIMINFO.DisplayStats) { - printk("Disabled interrupt moderation\n"); - } -} - -/******************************************************************************* -** Function : ResizeDimTimerDuration(); -** Description : Checks the current used descriptor ratio and resizes the -** duration timer (longer/smaller) if possible. -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : - -** Notes : There are both maximum and minimum timer duration value. -** This function assumes that interrupt moderation is already -** enabled! -*******************************************************************************/ - -static void -ResizeDimTimerDuration(SK_AC *pAC) { - SK_BOOL IncreaseTimerDuration; - int TotalMaxNbrDescr; - int UsedDescrRatio; - int RatioDiffAbs; - int RatioDiffRel; - int NewMaxModIntsPerSec; - int ModAdjValue; - long ModBase; - - /* - ** Check first if we are allowed to perform any modification - */ - if (IsIntModEnabled(pAC)) { - if (M_DIMINFO.IntModTypeSelect != C_INT_MOD_DYNAMIC) { - return; - } else { - if (M_DIMINFO.ModJustEnabled) { - M_DIMINFO.ModJustEnabled = SK_FALSE; - return; - } - } - } - - /* - ** If we got until here, we have to evaluate the amount of the - ** descriptor ratio change... - */ - TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC); - UsedDescrRatio = (M_DIMINFO.NbrProcessedDescr * 100) / TotalMaxNbrDescr; - - if (UsedDescrRatio > M_DIMINFO.PrevUsedDescrRatio) { - RatioDiffAbs = (UsedDescrRatio - M_DIMINFO.PrevUsedDescrRatio); - RatioDiffRel = (RatioDiffAbs * 100) / UsedDescrRatio; - M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; - IncreaseTimerDuration = SK_FALSE; /* in other words: DECREASE */ - } else if (UsedDescrRatio < M_DIMINFO.PrevUsedDescrRatio) { - RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio); - RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio; - M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; - IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */ - } else { - RatioDiffAbs = (M_DIMINFO.PrevUsedDescrRatio - UsedDescrRatio); - RatioDiffRel = (RatioDiffAbs * 100) / M_DIMINFO.PrevUsedDescrRatio; - M_DIMINFO.PrevUsedDescrRatio = UsedDescrRatio; - IncreaseTimerDuration = SK_TRUE; /* in other words: INCREASE */ - } - - /* - ** Now we can determine the change in percent - */ - if ((RatioDiffRel >= 0) && (RatioDiffRel <= 5) ) { - ModAdjValue = 1; /* 1% change - maybe some other value in future */ - } else if ((RatioDiffRel > 5) && (RatioDiffRel <= 10) ) { - ModAdjValue = 1; /* 1% change - maybe some other value in future */ - } else if ((RatioDiffRel > 10) && (RatioDiffRel <= 15) ) { - ModAdjValue = 1; /* 1% change - maybe some other value in future */ - } else { - ModAdjValue = 1; /* 1% change - maybe some other value in future */ - } - - if (IncreaseTimerDuration) { - NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec + - (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100; - } else { - NewMaxModIntsPerSec = M_DIMINFO.MaxModIntsPerSec - - (M_DIMINFO.MaxModIntsPerSec * ModAdjValue) / 100; - } - - /* - ** Check if we exceed boundaries... - */ - if ( (NewMaxModIntsPerSec > M_DIMINFO.MaxModIntsPerSecUpperLimit) || - (NewMaxModIntsPerSec < M_DIMINFO.MaxModIntsPerSecLowerLimit)) { - if (M_DIMINFO.DisplayStats) { - printk("Cannot change ModTim from %i to %i ints/sec\n", - M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec); - } - return; - } else { - if (M_DIMINFO.DisplayStats) { - printk("Resized ModTim from %i to %i ints/sec\n", - M_DIMINFO.MaxModIntsPerSec, NewMaxModIntsPerSec); - } - } - - M_DIMINFO.MaxModIntsPerSec = NewMaxModIntsPerSec; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - ModBase = C_CLK_FREQ_GENESIS / pAC->DynIrqModInfo.MaxModIntsPerSec; - } else { - ModBase = C_CLK_FREQ_YUKON / pAC->DynIrqModInfo.MaxModIntsPerSec; - } - - /* - ** We do not need to touch any other registers - */ - SK_OUT32(pAC->IoBase, B2_IRQM_INI, ModBase); -} - -/******************************************************************************* -** Function : DisplaySelectedModerationType() -** Description : Displays what type of moderation we have -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : void! -** Notes : - -*******************************************************************************/ - -static void -DisplaySelectedModerationType(SK_AC *pAC) { - - if (pAC->DynIrqModInfo.DisplayStats) { - if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) { - printk("Static int moderation runs with %i INTS/sec\n", - pAC->DynIrqModInfo.MaxModIntsPerSec); - } else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) { - if (IsIntModEnabled(pAC)) { - printk("Dynamic int moderation runs with %i INTS/sec\n", - pAC->DynIrqModInfo.MaxModIntsPerSec); - } else { - printk("Dynamic int moderation currently not applied\n"); - } - } else { - printk("No interrupt moderation selected!\n"); - } - } -} - -/******************************************************************************* -** Function : DisplaySelectedModerationMask() -** Description : Displays what interrupts are moderated -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : void! -** Notes : - -*******************************************************************************/ - -static void -DisplaySelectedModerationMask(SK_AC *pAC) { - - if (pAC->DynIrqModInfo.DisplayStats) { - if (pAC->DynIrqModInfo.IntModTypeSelect != C_INT_MOD_NONE) { - switch (pAC->DynIrqModInfo.MaskIrqModeration) { - case IRQ_MASK_TX_ONLY: - printk("Only Tx-interrupts are moderated\n"); - break; - case IRQ_MASK_RX_ONLY: - printk("Only Rx-interrupts are moderated\n"); - break; - case IRQ_MASK_SP_ONLY: - printk("Only special-interrupts are moderated\n"); - break; - case IRQ_MASK_TX_RX: - printk("Tx- and Rx-interrupts are moderated\n"); - break; - case IRQ_MASK_SP_RX: - printk("Special- and Rx-interrupts are moderated\n"); - break; - case IRQ_MASK_SP_TX: - printk("Special- and Tx-interrupts are moderated\n"); - break; - case IRQ_MASK_RX_TX_SP: - printk("All Rx-, Tx and special-interrupts are moderated\n"); - break; - default: - printk("Don't know what is moderated\n"); - break; - } - } else { - printk("No specific interrupts masked for moderation\n"); - } - } -} - -/******************************************************************************* -** Function : DisplayDescrRatio -** Description : Like the name states... -** Programmer : Ralph Roesler -** Last Modified: 23-mar-03 -** Returns : void! -** Notes : - -*******************************************************************************/ - -static void -DisplayDescrRatio(SK_AC *pAC) { - int TotalMaxNbrDescr = 0; - - if (pAC->DynIrqModInfo.DisplayStats) { - TotalMaxNbrDescr = pAC->RxDescrPerRing * GetRxCalls(pAC); - printk("Ratio descriptors: %i/%i\n", - M_DIMINFO.NbrProcessedDescr, TotalMaxNbrDescr); - } -} - -/******************************************************************************* -** -** End of file -** -*******************************************************************************/ diff --git a/drivers/net/sk98lin/skethtool.c b/drivers/net/sk98lin/skethtool.c deleted file mode 100644 index 5a6da8950faa..000000000000 --- a/drivers/net/sk98lin/skethtool.c +++ /dev/null @@ -1,627 +0,0 @@ -/****************************************************************************** - * - * Name: skethtool.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.7 $ - * Date: $Date: 2004/09/29 13:32:07 $ - * Purpose: All functions regarding ethtool handling - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2004 Marvell. - * - * Driver for Marvell Yukon/2 chipset and SysKonnect Gigabit Ethernet - * Server Adapters. - * - * Author: Ralph Roesler (rroesler@syskonnect.de) - * Mirko Lindner (mlindner@syskonnect.de) - * - * Address all question to: linux@syskonnect.de - * - * The technical manual for the adapters is available from SysKonnect's - * web pages: www.syskonnect.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - *****************************************************************************/ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" -#include "h/skversion.h" - -#include -#include -#include - -/****************************************************************************** - * - * Defines - * - *****************************************************************************/ - -#define SUPP_COPPER_ALL (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | \ - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | \ - SUPPORTED_1000baseT_Half| SUPPORTED_1000baseT_Full| \ - SUPPORTED_TP) - -#define ADV_COPPER_ALL (ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | \ - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | \ - ADVERTISED_1000baseT_Half| ADVERTISED_1000baseT_Full| \ - ADVERTISED_TP) - -#define SUPP_FIBRE_ALL (SUPPORTED_1000baseT_Full | \ - SUPPORTED_FIBRE | \ - SUPPORTED_Autoneg) - -#define ADV_FIBRE_ALL (ADVERTISED_1000baseT_Full | \ - ADVERTISED_FIBRE | \ - ADVERTISED_Autoneg) - - -/****************************************************************************** - * - * Local Functions - * - *****************************************************************************/ - -/***************************************************************************** - * - * getSettings - retrieves the current settings of the selected adapter - * - * Description: - * The current configuration of the selected adapter is returned. - * This configuration involves a)speed, b)duplex and c)autoneg plus - * a number of other variables. - * - * Returns: always 0 - * - */ -static int getSettings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - const DEV_NET *pNet = netdev_priv(dev); - int port = pNet->PortNr; - const SK_AC *pAC = pNet->pAC; - const SK_GEPORT *pPort = &pAC->GIni.GP[port]; - - static int DuplexAutoNegConfMap[9][3]= { - { -1 , -1 , -1 }, - { 0 , -1 , -1 }, - { SK_LMODE_HALF , DUPLEX_HALF, AUTONEG_DISABLE }, - { SK_LMODE_FULL , DUPLEX_FULL, AUTONEG_DISABLE }, - { SK_LMODE_AUTOHALF , DUPLEX_HALF, AUTONEG_ENABLE }, - { SK_LMODE_AUTOFULL , DUPLEX_FULL, AUTONEG_ENABLE }, - { SK_LMODE_AUTOBOTH , DUPLEX_FULL, AUTONEG_ENABLE }, - { SK_LMODE_AUTOSENSE , -1 , -1 }, - { SK_LMODE_INDETERMINATED, -1 , -1 } - }; - static int SpeedConfMap[6][2] = { - { 0 , -1 }, - { SK_LSPEED_AUTO , -1 }, - { SK_LSPEED_10MBPS , SPEED_10 }, - { SK_LSPEED_100MBPS , SPEED_100 }, - { SK_LSPEED_1000MBPS , SPEED_1000 }, - { SK_LSPEED_INDETERMINATED, -1 } - }; - static int AdvSpeedMap[6][2] = { - { 0 , -1 }, - { SK_LSPEED_AUTO , -1 }, - { SK_LSPEED_10MBPS , ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full }, - { SK_LSPEED_100MBPS , ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full }, - { SK_LSPEED_1000MBPS , ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full}, - { SK_LSPEED_INDETERMINATED, -1 } - }; - - ecmd->phy_address = port; - ecmd->speed = SpeedConfMap[pPort->PLinkSpeedUsed][1]; - ecmd->duplex = DuplexAutoNegConfMap[pPort->PLinkModeStatus][1]; - ecmd->autoneg = DuplexAutoNegConfMap[pPort->PLinkModeStatus][2]; - ecmd->transceiver = XCVR_INTERNAL; - - if (pAC->GIni.GICopperType) { - ecmd->port = PORT_TP; - ecmd->supported = (SUPP_COPPER_ALL|SUPPORTED_Autoneg); - if (pAC->GIni.GIGenesis) { - ecmd->supported &= ~(SUPPORTED_10baseT_Half); - ecmd->supported &= ~(SUPPORTED_10baseT_Full); - ecmd->supported &= ~(SUPPORTED_100baseT_Half); - ecmd->supported &= ~(SUPPORTED_100baseT_Full); - } else { - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - ecmd->supported &= ~(SUPPORTED_1000baseT_Half); - } -#ifdef CHIP_ID_YUKON_FE - if (pAC->GIni.GIChipId == CHIP_ID_YUKON_FE) { - ecmd->supported &= ~(SUPPORTED_1000baseT_Half); - ecmd->supported &= ~(SUPPORTED_1000baseT_Full); - } -#endif - } - if (pAC->GIni.GP[0].PLinkSpeed != SK_LSPEED_AUTO) { - ecmd->advertising = AdvSpeedMap[pPort->PLinkSpeed][1]; - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - ecmd->advertising &= ~(SUPPORTED_1000baseT_Half); - } - } else { - ecmd->advertising = ecmd->supported; - } - - if (ecmd->autoneg == AUTONEG_ENABLE) - ecmd->advertising |= ADVERTISED_Autoneg; - } else { - ecmd->port = PORT_FIBRE; - ecmd->supported = SUPP_FIBRE_ALL; - ecmd->advertising = ADV_FIBRE_ALL; - } - return 0; -} - -/* - * MIB infrastructure uses instance value starting at 1 - * based on board and port. - */ -static inline u32 pnmiInstance(const DEV_NET *pNet) -{ - return 1 + (pNet->pAC->RlmtNets == 2) + pNet->PortNr; -} - -/***************************************************************************** - * - * setSettings - configures the settings of a selected adapter - * - * Description: - * Possible settings that may be altered are a)speed, b)duplex or - * c)autonegotiation. - * - * Returns: - * 0: everything fine, no error - * <0: the return value is the error code of the failure - */ -static int setSettings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - u32 instance; - char buf[4]; - int len = 1; - - if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100 - && ecmd->speed != SPEED_1000) - return -EINVAL; - - if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) - return -EINVAL; - - if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) - return -EINVAL; - - if (ecmd->autoneg == AUTONEG_DISABLE) - *buf = (ecmd->duplex == DUPLEX_FULL) - ? SK_LMODE_FULL : SK_LMODE_HALF; - else - *buf = (ecmd->duplex == DUPLEX_FULL) - ? SK_LMODE_AUTOFULL : SK_LMODE_AUTOHALF; - - instance = pnmiInstance(pNet); - if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_LINK_MODE, - &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK) - return -EINVAL; - - switch(ecmd->speed) { - case SPEED_1000: - *buf = SK_LSPEED_1000MBPS; - break; - case SPEED_100: - *buf = SK_LSPEED_100MBPS; - break; - case SPEED_10: - *buf = SK_LSPEED_10MBPS; - } - - if (SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, - &buf, &len, instance, pNet->NetNr) != SK_PNMI_ERR_OK) - return -EINVAL; - - return 0; -} - -/***************************************************************************** - * - * getDriverInfo - returns generic driver and adapter information - * - * Description: - * Generic driver information is returned via this function, such as - * the name of the driver, its version and and firmware version. - * In addition to this, the location of the selected adapter is - * returned as a bus info string (e.g. '01:05.0'). - * - * Returns: N/A - * - */ -static void getDriverInfo(struct net_device *dev, struct ethtool_drvinfo *info) -{ - const DEV_NET *pNet = netdev_priv(dev); - const SK_AC *pAC = pNet->pAC; - char vers[32]; - - snprintf(vers, sizeof(vers)-1, VER_STRING "(v%d.%d)", - (pAC->GIni.GIPciHwRev >> 4) & 0xf, pAC->GIni.GIPciHwRev & 0xf); - - strlcpy(info->driver, DRIVER_FILE_NAME, sizeof(info->driver)); - strcpy(info->version, vers); - strcpy(info->fw_version, "N/A"); - strlcpy(info->bus_info, pci_name(pAC->PciDev), ETHTOOL_BUSINFO_LEN); -} - -/* - * Ethtool statistics support. - */ -static const char StringsStats[][ETH_GSTRING_LEN] = { - "rx_packets", "tx_packets", - "rx_bytes", "tx_bytes", - "rx_errors", "tx_errors", - "rx_dropped", "tx_dropped", - "multicasts", "collisions", - "rx_length_errors", "rx_buffer_overflow_errors", - "rx_crc_errors", "rx_frame_errors", - "rx_too_short_errors", "rx_too_long_errors", - "rx_carrier_extension_errors", "rx_symbol_errors", - "rx_llc_mac_size_errors", "rx_carrier_errors", - "rx_jabber_errors", "rx_missed_errors", - "tx_abort_collision_errors", "tx_carrier_errors", - "tx_buffer_underrun_errors", "tx_heartbeat_errors", - "tx_window_errors", -}; - -static int getStatsCount(struct net_device *dev) -{ - return ARRAY_SIZE(StringsStats); -} - -static void getStrings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *StringsStats, sizeof(StringsStats)); - break; - } -} - -static void getEthtoolStats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - const DEV_NET *pNet = netdev_priv(dev); - const SK_AC *pAC = pNet->pAC; - const SK_PNMI_STRUCT_DATA *pPnmiStruct = &pAC->PnmiStruct; - - *data++ = pPnmiStruct->Stat[0].StatRxOkCts; - *data++ = pPnmiStruct->Stat[0].StatTxOkCts; - *data++ = pPnmiStruct->Stat[0].StatRxOctetsOkCts; - *data++ = pPnmiStruct->Stat[0].StatTxOctetsOkCts; - *data++ = pPnmiStruct->InErrorsCts; - *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts; - *data++ = pPnmiStruct->RxNoBufCts; - *data++ = pPnmiStruct->TxNoBufCts; - *data++ = pPnmiStruct->Stat[0].StatRxMulticastOkCts; - *data++ = pPnmiStruct->Stat[0].StatTxSingleCollisionCts; - *data++ = pPnmiStruct->Stat[0].StatRxRuntCts; - *data++ = pPnmiStruct->Stat[0].StatRxFifoOverflowCts; - *data++ = pPnmiStruct->Stat[0].StatRxFcsCts; - *data++ = pPnmiStruct->Stat[0].StatRxFramingCts; - *data++ = pPnmiStruct->Stat[0].StatRxShortsCts; - *data++ = pPnmiStruct->Stat[0].StatRxTooLongCts; - *data++ = pPnmiStruct->Stat[0].StatRxCextCts; - *data++ = pPnmiStruct->Stat[0].StatRxSymbolCts; - *data++ = pPnmiStruct->Stat[0].StatRxIRLengthCts; - *data++ = pPnmiStruct->Stat[0].StatRxCarrierCts; - *data++ = pPnmiStruct->Stat[0].StatRxJabberCts; - *data++ = pPnmiStruct->Stat[0].StatRxMissedCts; - *data++ = pAC->stats.tx_aborted_errors; - *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts; - *data++ = pPnmiStruct->Stat[0].StatTxFifoUnderrunCts; - *data++ = pPnmiStruct->Stat[0].StatTxCarrierCts; - *data++ = pAC->stats.tx_window_errors; -} - - -/***************************************************************************** - * - * toggleLeds - Changes the LED state of an adapter - * - * Description: - * This function changes the current state of all LEDs of an adapter so - * that it can be located by a user. - * - * Returns: N/A - * - */ -static void toggleLeds(DEV_NET *pNet, int on) -{ - SK_AC *pAC = pNet->pAC; - int port = pNet->PortNr; - void __iomem *io = pAC->IoBase; - - if (pAC->GIni.GIGenesis) { - SK_OUT8(io, MR_ADDR(port,LNK_LED_REG), - on ? SK_LNK_ON : SK_LNK_OFF); - SkGeYellowLED(pAC, io, - on ? (LED_ON >> 1) : (LED_OFF >> 1)); - SkGeXmitLED(pAC, io, MR_ADDR(port,RX_LED_INI), - on ? SK_LED_TST : SK_LED_DIS); - - if (pAC->GIni.GP[port].PhyType == SK_PHY_BCOM) - SkXmPhyWrite(pAC, io, port, PHY_BCOM_P_EXT_CTRL, - on ? PHY_B_PEC_LED_ON : PHY_B_PEC_LED_OFF); - else if (pAC->GIni.GP[port].PhyType == SK_PHY_LONE) - SkXmPhyWrite(pAC, io, port, PHY_LONE_LED_CFG, - on ? 0x0800 : PHY_L_LC_LEDT); - else - SkGeXmitLED(pAC, io, MR_ADDR(port,TX_LED_INI), - on ? SK_LED_TST : SK_LED_DIS); - } else { - const u16 YukLedOn = (PHY_M_LED_MO_DUP(MO_LED_ON) | - PHY_M_LED_MO_10(MO_LED_ON) | - PHY_M_LED_MO_100(MO_LED_ON) | - PHY_M_LED_MO_1000(MO_LED_ON) | - PHY_M_LED_MO_RX(MO_LED_ON)); - const u16 YukLedOff = (PHY_M_LED_MO_DUP(MO_LED_OFF) | - PHY_M_LED_MO_10(MO_LED_OFF) | - PHY_M_LED_MO_100(MO_LED_OFF) | - PHY_M_LED_MO_1000(MO_LED_OFF) | - PHY_M_LED_MO_RX(MO_LED_OFF)); - - - SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_CTRL,0); - SkGmPhyWrite(pAC,io,port,PHY_MARV_LED_OVER, - on ? YukLedOn : YukLedOff); - } -} - -/***************************************************************************** - * - * skGeBlinkTimer - Changes the LED state of an adapter - * - * Description: - * This function changes the current state of all LEDs of an adapter so - * that it can be located by a user. If the requested time interval for - * this test has elapsed, this function cleans up everything that was - * temporarily setup during the locate NIC test. This involves of course - * also closing or opening any adapter so that the initial board state - * is recovered. - * - * Returns: N/A - * - */ -void SkGeBlinkTimer(unsigned long data) -{ - struct net_device *dev = (struct net_device *) data; - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - toggleLeds(pNet, pAC->LedsOn); - - pAC->LedsOn = !pAC->LedsOn; - mod_timer(&pAC->BlinkTimer, jiffies + HZ/4); -} - -/***************************************************************************** - * - * locateDevice - start the locate NIC feature of the elected adapter - * - * Description: - * This function is used if the user want to locate a particular NIC. - * All LEDs are regularly switched on and off, so the NIC can easily - * be identified. - * - * Returns: - * ==0: everything fine, no error, locateNIC test was started - * !=0: one locateNIC test runs already - * - */ -static int locateDevice(struct net_device *dev, u32 data) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - if(!data || data > (u32)(MAX_SCHEDULE_TIMEOUT / HZ)) - data = (u32)(MAX_SCHEDULE_TIMEOUT / HZ); - - /* start blinking */ - pAC->LedsOn = 0; - mod_timer(&pAC->BlinkTimer, jiffies); - msleep_interruptible(data * 1000); - del_timer_sync(&pAC->BlinkTimer); - toggleLeds(pNet, 0); - - return 0; -} - -/***************************************************************************** - * - * getPauseParams - retrieves the pause parameters - * - * Description: - * All current pause parameters of a selected adapter are placed - * in the passed ethtool_pauseparam structure and are returned. - * - * Returns: N/A - * - */ -static void getPauseParams(struct net_device *dev, struct ethtool_pauseparam *epause) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr]; - - epause->rx_pause = (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC) || - (pPort->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM); - - epause->tx_pause = epause->rx_pause || (pPort->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND); - epause->autoneg = epause->rx_pause || epause->tx_pause; -} - -/***************************************************************************** - * - * setPauseParams - configures the pause parameters of an adapter - * - * Description: - * This function sets the Rx or Tx pause parameters - * - * Returns: - * ==0: everything fine, no error - * !=0: the return value is the error code of the failure - */ -static int setPauseParams(struct net_device *dev , struct ethtool_pauseparam *epause) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - SK_GEPORT *pPort = &pAC->GIni.GP[pNet->PortNr]; - u32 instance = pnmiInstance(pNet); - struct ethtool_pauseparam old; - u8 oldspeed = pPort->PLinkSpeedUsed; - char buf[4]; - int len = 1; - int ret; - - /* - ** we have to determine the current settings to see if - ** the operator requested any modification of the flow - ** control parameters... - */ - getPauseParams(dev, &old); - - /* - ** perform modifications regarding the changes - ** requested by the operator - */ - if (epause->autoneg != old.autoneg) - *buf = epause->autoneg ? SK_FLOW_MODE_NONE : SK_FLOW_MODE_SYMMETRIC; - else { - if (epause->rx_pause && epause->tx_pause) - *buf = SK_FLOW_MODE_SYMMETRIC; - else if (epause->rx_pause && !epause->tx_pause) - *buf = SK_FLOW_MODE_SYM_OR_REM; - else if (!epause->rx_pause && epause->tx_pause) - *buf = SK_FLOW_MODE_LOC_SEND; - else - *buf = SK_FLOW_MODE_NONE; - } - - ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_FLOWCTRL_MODE, - &buf, &len, instance, pNet->NetNr); - - if (ret != SK_PNMI_ERR_OK) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL, - ("ethtool (sk98lin): error changing rx/tx pause (%i)\n", ret)); - goto err; - } - - /* - ** It may be that autoneg has been disabled! Therefore - ** set the speed to the previously used value... - */ - if (!epause->autoneg) { - len = 1; - ret = SkPnmiSetVar(pAC, pAC->IoBase, OID_SKGE_SPEED_MODE, - &oldspeed, &len, instance, pNet->NetNr); - if (ret != SK_PNMI_ERR_OK) - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_CTRL, - ("ethtool (sk98lin): error setting speed (%i)\n", ret)); - } - err: - return ret ? -EIO : 0; -} - -/* Only Yukon supports checksum offload. */ -static int setScatterGather(struct net_device *dev, u32 data) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) - return -EOPNOTSUPP; - return ethtool_op_set_sg(dev, data); -} - -static int setTxCsum(struct net_device *dev, u32 data) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) - return -EOPNOTSUPP; - - return ethtool_op_set_tx_csum(dev, data); -} - -static u32 getRxCsum(struct net_device *dev) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - return pAC->RxPort[pNet->PortNr].RxCsum; -} - -static int setRxCsum(struct net_device *dev, u32 data) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) - return -EOPNOTSUPP; - - pAC->RxPort[pNet->PortNr].RxCsum = data != 0; - return 0; -} - -static int getRegsLen(struct net_device *dev) -{ - return 0x4000; -} - -/* - * Returns copy of whole control register region - * Note: skip RAM address register because accessing it will - * cause bus hangs! - */ -static void getRegs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - DEV_NET *pNet = netdev_priv(dev); - const void __iomem *io = pNet->pAC->IoBase; - - regs->version = 1; - memset(p, 0, regs->len); - memcpy_fromio(p, io, B3_RAM_ADDR); - - memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, - regs->len - B3_RI_WTO_R1); -} - -const struct ethtool_ops SkGeEthtoolOps = { - .get_settings = getSettings, - .set_settings = setSettings, - .get_drvinfo = getDriverInfo, - .get_strings = getStrings, - .get_stats_count = getStatsCount, - .get_ethtool_stats = getEthtoolStats, - .phys_id = locateDevice, - .get_pauseparam = getPauseParams, - .set_pauseparam = setPauseParams, - .get_link = ethtool_op_get_link, - .get_sg = ethtool_op_get_sg, - .set_sg = setScatterGather, - .get_tx_csum = ethtool_op_get_tx_csum, - .set_tx_csum = setTxCsum, - .get_rx_csum = getRxCsum, - .set_rx_csum = setRxCsum, - .get_regs = getRegs, - .get_regs_len = getRegsLen, -}; diff --git a/drivers/net/sk98lin/skge.c b/drivers/net/sk98lin/skge.c deleted file mode 100644 index 20890e44f99a..000000000000 --- a/drivers/net/sk98lin/skge.c +++ /dev/null @@ -1,5218 +0,0 @@ -/****************************************************************************** - * - * Name: skge.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.45 $ - * Date: $Date: 2004/02/12 14:41:02 $ - * Purpose: The main driver source module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * Driver for Marvell Yukon chipset and SysKonnect Gigabit Ethernet - * Server Adapters. - * - * Created 10-Feb-1999, based on Linux' acenic.c, 3c59x.c and - * SysKonnects GEnesis Solaris driver - * Author: Christoph Goos (cgoos@syskonnect.de) - * Mirko Lindner (mlindner@syskonnect.de) - * - * Address all question to: linux@syskonnect.de - * - * The technical manual for the adapters is available from SysKonnect's - * web pages: www.syskonnect.com - * Goto "Support" and search Knowledge Base for "manual". - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Possible compiler options (#define xxx / -Dxxx): - * - * debugging can be enable by changing SK_DEBUG_CHKMOD and - * SK_DEBUG_CHKCAT in makefile (described there). - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This is the main module of the Linux GE driver. - * - * All source files except skge.c, skdrv1st.h, skdrv2nd.h and sktypes.h - * are part of SysKonnect's COMMON MODULES for the SK-98xx adapters. - * Those are used for drivers on multiple OS', so some thing may seem - * unnecessary complicated on Linux. Please do not try to 'clean up' - * them without VERY good reasons, because this will make it more - * difficult to keep the Linux driver in synchronisation with the - * other versions. - * - * Include file hierarchy: - * - * - * - * "h/skdrv1st.h" - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * those three depending on kernel version used: - * - * - * - * - * - * "h/skerror.h" - * "h/skdebug.h" - * "h/sktypes.h" - * "h/lm80.h" - * "h/xmac_ii.h" - * - * "h/skdrv2nd.h" - * "h/skqueue.h" - * "h/skgehwt.h" - * "h/sktimer.h" - * "h/ski2c.h" - * "h/skgepnmi.h" - * "h/skvpd.h" - * "h/skgehw.h" - * "h/skgeinit.h" - * "h/skaddr.h" - * "h/skgesirq.h" - * "h/skrlmt.h" - * - ******************************************************************************/ - -#include "h/skversion.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/******************************************************************************* - * - * Defines - * - ******************************************************************************/ - -/* for debuging on x86 only */ -/* #define BREAKPOINT() asm(" int $3"); */ - -/* use the transmit hw checksum driver functionality */ -#define USE_SK_TX_CHECKSUM - -/* use the receive hw checksum driver functionality */ -#define USE_SK_RX_CHECKSUM - -/* use the scatter-gather functionality with sendfile() */ -#define SK_ZEROCOPY - -/* use of a transmit complete interrupt */ -#define USE_TX_COMPLETE - -/* - * threshold for copying small receive frames - * set to 0 to avoid copying, set to 9001 to copy all frames - */ -#define SK_COPY_THRESHOLD 50 - -/* number of adapters that can be configured via command line params */ -#define SK_MAX_CARD_PARAM 16 - - - -/* - * use those defines for a compile-in version of the driver instead - * of command line parameters - */ -// #define LINK_SPEED_A {"Auto", } -// #define LINK_SPEED_B {"Auto", } -// #define AUTO_NEG_A {"Sense", } -// #define AUTO_NEG_B {"Sense", } -// #define DUP_CAP_A {"Both", } -// #define DUP_CAP_B {"Both", } -// #define FLOW_CTRL_A {"SymOrRem", } -// #define FLOW_CTRL_B {"SymOrRem", } -// #define ROLE_A {"Auto", } -// #define ROLE_B {"Auto", } -// #define PREF_PORT {"A", } -// #define CON_TYPE {"Auto", } -// #define RLMT_MODE {"CheckLinkState", } - -#define DEV_KFREE_SKB(skb) dev_kfree_skb(skb) -#define DEV_KFREE_SKB_IRQ(skb) dev_kfree_skb_irq(skb) -#define DEV_KFREE_SKB_ANY(skb) dev_kfree_skb_any(skb) - - -/* Set blink mode*/ -#define OEM_CONFIG_VALUE ( SK_ACT_LED_BLINK | \ - SK_DUP_LED_NORMAL | \ - SK_LED_LINK100_ON) - - -/* Isr return value */ -#define SkIsrRetVar irqreturn_t -#define SkIsrRetNone IRQ_NONE -#define SkIsrRetHandled IRQ_HANDLED - - -/******************************************************************************* - * - * Local Function Prototypes - * - ******************************************************************************/ - -static void FreeResources(struct SK_NET_DEVICE *dev); -static int SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC); -static SK_BOOL BoardAllocMem(SK_AC *pAC); -static void BoardFreeMem(SK_AC *pAC); -static void BoardInitMem(SK_AC *pAC); -static void SetupRing(SK_AC*, void*, uintptr_t, RXD**, RXD**, RXD**, int*, SK_BOOL); -static SkIsrRetVar SkGeIsr(int irq, void *dev_id); -static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id); -static int SkGeOpen(struct SK_NET_DEVICE *dev); -static int SkGeClose(struct SK_NET_DEVICE *dev); -static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev); -static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p); -static void SkGeSetRxMode(struct SK_NET_DEVICE *dev); -static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev); -static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd); -static void GetConfiguration(SK_AC*); -static int XmitFrame(SK_AC*, TX_PORT*, struct sk_buff*); -static void FreeTxDescriptors(SK_AC*pAC, TX_PORT*); -static void FillRxRing(SK_AC*, RX_PORT*); -static SK_BOOL FillRxDescriptor(SK_AC*, RX_PORT*); -static void ReceiveIrq(SK_AC*, RX_PORT*, SK_BOOL); -static void ClearAndStartRx(SK_AC*, int); -static void ClearTxIrq(SK_AC*, int, int); -static void ClearRxRing(SK_AC*, RX_PORT*); -static void ClearTxRing(SK_AC*, TX_PORT*); -static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int new_mtu); -static void PortReInitBmu(SK_AC*, int); -static int SkGeIocMib(DEV_NET*, unsigned int, int); -static int SkGeInitPCI(SK_AC *pAC); -static void StartDrvCleanupTimer(SK_AC *pAC); -static void StopDrvCleanupTimer(SK_AC *pAC); -static int XmitFrameSG(SK_AC*, TX_PORT*, struct sk_buff*); - -#ifdef SK_DIAG_SUPPORT -static SK_U32 ParseDeviceNbrFromSlotName(const char *SlotName); -static int SkDrvInitAdapter(SK_AC *pAC, int devNbr); -static int SkDrvDeInitAdapter(SK_AC *pAC, int devNbr); -#endif - -/******************************************************************************* - * - * Extern Function Prototypes - * - ******************************************************************************/ -extern void SkDimEnableModerationIfNeeded(SK_AC *pAC); -extern void SkDimDisplayModerationSettings(SK_AC *pAC); -extern void SkDimStartModerationTimer(SK_AC *pAC); -extern void SkDimModerate(SK_AC *pAC); -extern void SkGeBlinkTimer(unsigned long data); - -#ifdef DEBUG -static void DumpMsg(struct sk_buff*, char*); -static void DumpData(char*, int); -static void DumpLong(char*, int); -#endif - -/* global variables *********************************************************/ -static SK_BOOL DoPrintInterfaceChange = SK_TRUE; -extern const struct ethtool_ops SkGeEthtoolOps; - -/* local variables **********************************************************/ -static uintptr_t TxQueueAddr[SK_MAX_MACS][2] = {{0x680, 0x600},{0x780, 0x700}}; -static uintptr_t RxQueueAddr[SK_MAX_MACS] = {0x400, 0x480}; - -/***************************************************************************** - * - * SkPciWriteCfgDWord - write a 32 bit value to pci config space - * - * Description: - * This routine writes a 32 bit value to the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -static inline int SkPciWriteCfgDWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U32 Val) /* pointer to store the read value */ -{ - pci_write_config_dword(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgDWord */ - -/***************************************************************************** - * - * SkGeInitPCI - Init the PCI resources - * - * Description: - * This function initialize the PCI resources and IO - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -static __devinit int SkGeInitPCI(SK_AC *pAC) -{ - struct SK_NET_DEVICE *dev = pAC->dev[0]; - struct pci_dev *pdev = pAC->PciDev; - int retval; - - dev->mem_start = pci_resource_start (pdev, 0); - pci_set_master(pdev); - - retval = pci_request_regions(pdev, "sk98lin"); - if (retval) - goto out; - -#ifdef SK_BIG_ENDIAN - /* - * On big endian machines, we use the adapter's aibility of - * reading the descriptors as big endian. - */ - { - SK_U32 our2; - SkPciReadCfgDWord(pAC, PCI_OUR_REG_2, &our2); - our2 |= PCI_REV_DESC; - SkPciWriteCfgDWord(pAC, PCI_OUR_REG_2, our2); - } -#endif - - /* - * Remap the regs into kernel space. - */ - pAC->IoBase = ioremap_nocache(dev->mem_start, 0x4000); - if (!pAC->IoBase) { - retval = -EIO; - goto out_release; - } - - return 0; - - out_release: - pci_release_regions(pdev); - out: - return retval; -} - - -/***************************************************************************** - * - * FreeResources - release resources allocated for adapter - * - * Description: - * This function releases the IRQ, unmaps the IO and - * frees the desriptor ring. - * - * Returns: N/A - * - */ -static void FreeResources(struct SK_NET_DEVICE *dev) -{ -SK_U32 AllocFlag; -DEV_NET *pNet; -SK_AC *pAC; - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - AllocFlag = pAC->AllocFlag; - if (pAC->PciDev) { - pci_release_regions(pAC->PciDev); - } - if (AllocFlag & SK_ALLOC_IRQ) { - free_irq(dev->irq, dev); - } - if (pAC->IoBase) { - iounmap(pAC->IoBase); - } - if (pAC->pDescrMem) { - BoardFreeMem(pAC); - } - -} /* FreeResources */ - -MODULE_AUTHOR("Mirko Lindner "); -MODULE_DESCRIPTION("SysKonnect SK-NET Gigabit Ethernet SK-98xx driver"); -MODULE_LICENSE("GPL"); - -#ifdef LINK_SPEED_A -static char *Speed_A[SK_MAX_CARD_PARAM] = LINK_SPEED; -#else -static char *Speed_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef LINK_SPEED_B -static char *Speed_B[SK_MAX_CARD_PARAM] = LINK_SPEED; -#else -static char *Speed_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef AUTO_NEG_A -static char *AutoNeg_A[SK_MAX_CARD_PARAM] = AUTO_NEG_A; -#else -static char *AutoNeg_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef DUP_CAP_A -static char *DupCap_A[SK_MAX_CARD_PARAM] = DUP_CAP_A; -#else -static char *DupCap_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef FLOW_CTRL_A -static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = FLOW_CTRL_A; -#else -static char *FlowCtrl_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef ROLE_A -static char *Role_A[SK_MAX_CARD_PARAM] = ROLE_A; -#else -static char *Role_A[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef AUTO_NEG_B -static char *AutoNeg_B[SK_MAX_CARD_PARAM] = AUTO_NEG_B; -#else -static char *AutoNeg_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef DUP_CAP_B -static char *DupCap_B[SK_MAX_CARD_PARAM] = DUP_CAP_B; -#else -static char *DupCap_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef FLOW_CTRL_B -static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = FLOW_CTRL_B; -#else -static char *FlowCtrl_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef ROLE_B -static char *Role_B[SK_MAX_CARD_PARAM] = ROLE_B; -#else -static char *Role_B[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef CON_TYPE -static char *ConType[SK_MAX_CARD_PARAM] = CON_TYPE; -#else -static char *ConType[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef PREF_PORT -static char *PrefPort[SK_MAX_CARD_PARAM] = PREF_PORT; -#else -static char *PrefPort[SK_MAX_CARD_PARAM] = {"", }; -#endif - -#ifdef RLMT_MODE -static char *RlmtMode[SK_MAX_CARD_PARAM] = RLMT_MODE; -#else -static char *RlmtMode[SK_MAX_CARD_PARAM] = {"", }; -#endif - -static int IntsPerSec[SK_MAX_CARD_PARAM]; -static char *Moderation[SK_MAX_CARD_PARAM]; -static char *ModerationMask[SK_MAX_CARD_PARAM]; -static char *AutoSizing[SK_MAX_CARD_PARAM]; -static char *Stats[SK_MAX_CARD_PARAM]; - -module_param_array(Speed_A, charp, NULL, 0); -module_param_array(Speed_B, charp, NULL, 0); -module_param_array(AutoNeg_A, charp, NULL, 0); -module_param_array(AutoNeg_B, charp, NULL, 0); -module_param_array(DupCap_A, charp, NULL, 0); -module_param_array(DupCap_B, charp, NULL, 0); -module_param_array(FlowCtrl_A, charp, NULL, 0); -module_param_array(FlowCtrl_B, charp, NULL, 0); -module_param_array(Role_A, charp, NULL, 0); -module_param_array(Role_B, charp, NULL, 0); -module_param_array(ConType, charp, NULL, 0); -module_param_array(PrefPort, charp, NULL, 0); -module_param_array(RlmtMode, charp, NULL, 0); -/* used for interrupt moderation */ -module_param_array(IntsPerSec, int, NULL, 0); -module_param_array(Moderation, charp, NULL, 0); -module_param_array(Stats, charp, NULL, 0); -module_param_array(ModerationMask, charp, NULL, 0); -module_param_array(AutoSizing, charp, NULL, 0); - -/***************************************************************************** - * - * SkGeBoardInit - do level 0 and 1 initialization - * - * Description: - * This function prepares the board hardware for running. The desriptor - * ring is set up, the IRQ is allocated and the configuration settings - * are examined. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int __devinit SkGeBoardInit(struct SK_NET_DEVICE *dev, SK_AC *pAC) -{ -short i; -unsigned long Flags; -char *DescrString = "sk98lin: Driver for Linux"; /* this is given to PNMI */ -char *VerStr = VER_STRING; -int Ret; /* return code of request_irq */ -SK_BOOL DualNet; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("IoBase: %08lX\n", (unsigned long)pAC->IoBase)); - for (i=0; iTxPort[i][0].HwAddr = pAC->IoBase + TxQueueAddr[i][0]; - pAC->TxPort[i][0].PortIndex = i; - pAC->RxPort[i].HwAddr = pAC->IoBase + RxQueueAddr[i]; - pAC->RxPort[i].PortIndex = i; - } - - /* Initialize the mutexes */ - for (i=0; iTxPort[i][0].TxDesRingLock); - spin_lock_init(&pAC->RxPort[i].RxDesRingLock); - } - spin_lock_init(&pAC->SlowPathLock); - - /* setup phy_id blink timer */ - pAC->BlinkTimer.function = SkGeBlinkTimer; - pAC->BlinkTimer.data = (unsigned long) dev; - init_timer(&pAC->BlinkTimer); - - /* level 0 init common modules here */ - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - /* Does a RESET on board ...*/ - if (SkGeInit(pAC, pAC->IoBase, SK_INIT_DATA) != 0) { - printk("HWInit (0) failed.\n"); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return -EIO; - } - SkI2cInit( pAC, pAC->IoBase, SK_INIT_DATA); - SkEventInit(pAC, pAC->IoBase, SK_INIT_DATA); - SkPnmiInit( pAC, pAC->IoBase, SK_INIT_DATA); - SkAddrInit( pAC, pAC->IoBase, SK_INIT_DATA); - SkRlmtInit( pAC, pAC->IoBase, SK_INIT_DATA); - SkTimerInit(pAC, pAC->IoBase, SK_INIT_DATA); - - pAC->BoardLevel = SK_INIT_DATA; - pAC->RxBufSize = ETH_BUF_SIZE; - - SK_PNMI_SET_DRIVER_DESCR(pAC, DescrString); - SK_PNMI_SET_DRIVER_VER(pAC, VerStr); - - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - /* level 1 init common modules here (HW init) */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { - printk("sk98lin: HWInit (1) failed.\n"); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return -EIO; - } - SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); - SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); - SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO); - SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO); - SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO); - SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO); - - /* Set chipset type support */ - pAC->ChipsetType = 0; - if ((pAC->GIni.GIChipId == CHIP_ID_YUKON) || - (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE)) { - pAC->ChipsetType = 1; - } - - GetConfiguration(pAC); - if (pAC->RlmtNets == 2) { - pAC->GIni.GIPortUsage = SK_MUL_LINK; - } - - pAC->BoardLevel = SK_INIT_IO; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - if (pAC->GIni.GIMacsFound == 2) { - Ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev); - } else if (pAC->GIni.GIMacsFound == 1) { - Ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, - "sk98lin", dev); - } else { - printk(KERN_WARNING "sk98lin: Illegal number of ports: %d\n", - pAC->GIni.GIMacsFound); - return -EIO; - } - - if (Ret) { - printk(KERN_WARNING "sk98lin: Requested IRQ %d is busy.\n", - dev->irq); - return Ret; - } - pAC->AllocFlag |= SK_ALLOC_IRQ; - - /* Alloc memory for this board (Mem for RxD/TxD) : */ - if(!BoardAllocMem(pAC)) { - printk("No memory for descriptor rings.\n"); - return -ENOMEM; - } - - BoardInitMem(pAC); - /* tschilling: New common function with minimum size check. */ - DualNet = SK_FALSE; - if (pAC->RlmtNets == 2) { - DualNet = SK_TRUE; - } - - if (SkGeInitAssignRamToQueues( - pAC, - pAC->ActivePort, - DualNet)) { - BoardFreeMem(pAC); - printk("sk98lin: SkGeInitAssignRamToQueues failed.\n"); - return -EIO; - } - - return (0); -} /* SkGeBoardInit */ - - -/***************************************************************************** - * - * BoardAllocMem - allocate the memory for the descriptor rings - * - * Description: - * This function allocates the memory for all descriptor rings. - * Each ring is aligned for the desriptor alignment and no ring - * has a 4 GByte boundary in it (because the upper 32 bit must - * be constant for all descriptiors in one rings). - * - * Returns: - * SK_TRUE, if all memory could be allocated - * SK_FALSE, if not - */ -static __devinit SK_BOOL BoardAllocMem(SK_AC *pAC) -{ -caddr_t pDescrMem; /* pointer to descriptor memory area */ -size_t AllocLength; /* length of complete descriptor area */ -int i; /* loop counter */ -unsigned long BusAddr; - - - /* rings plus one for alignment (do not cross 4 GB boundary) */ - /* RX_RING_SIZE is assumed bigger than TX_RING_SIZE */ -#if (BITS_PER_LONG == 32) - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; -#else - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound - + RX_RING_SIZE + 8; -#endif - - pDescrMem = pci_alloc_consistent(pAC->PciDev, AllocLength, - &pAC->pDescrMemDMA); - - if (pDescrMem == NULL) { - return (SK_FALSE); - } - pAC->pDescrMem = pDescrMem; - BusAddr = (unsigned long) pAC->pDescrMemDMA; - - /* Descriptors need 8 byte alignment, and this is ensured - * by pci_alloc_consistent. - */ - for (i=0; iGIni.GIMacsFound; i++) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("TX%d/A: pDescrMem: %lX, PhysDescrMem: %lX\n", - i, (unsigned long) pDescrMem, - BusAddr)); - pAC->TxPort[i][0].pTxDescrRing = pDescrMem; - pAC->TxPort[i][0].VTxDescrRing = BusAddr; - pDescrMem += TX_RING_SIZE; - BusAddr += TX_RING_SIZE; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("RX%d: pDescrMem: %lX, PhysDescrMem: %lX\n", - i, (unsigned long) pDescrMem, - (unsigned long)BusAddr)); - pAC->RxPort[i].pRxDescrRing = pDescrMem; - pAC->RxPort[i].VRxDescrRing = BusAddr; - pDescrMem += RX_RING_SIZE; - BusAddr += RX_RING_SIZE; - } /* for */ - - return (SK_TRUE); -} /* BoardAllocMem */ - - -/**************************************************************************** - * - * BoardFreeMem - reverse of BoardAllocMem - * - * Description: - * Free all memory allocated in BoardAllocMem: adapter context, - * descriptor rings, locks. - * - * Returns: N/A - */ -static void BoardFreeMem( -SK_AC *pAC) -{ -size_t AllocLength; /* length of complete descriptor area */ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("BoardFreeMem\n")); -#if (BITS_PER_LONG == 32) - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound + 8; -#else - AllocLength = (RX_RING_SIZE + TX_RING_SIZE) * pAC->GIni.GIMacsFound - + RX_RING_SIZE + 8; -#endif - - pci_free_consistent(pAC->PciDev, AllocLength, - pAC->pDescrMem, pAC->pDescrMemDMA); - pAC->pDescrMem = NULL; -} /* BoardFreeMem */ - - -/***************************************************************************** - * - * BoardInitMem - initiate the descriptor rings - * - * Description: - * This function sets the descriptor rings up in memory. - * The adapter is initialized with the descriptor start addresses. - * - * Returns: N/A - */ -static __devinit void BoardInitMem(SK_AC *pAC) -{ -int i; /* loop counter */ -int RxDescrSize; /* the size of a rx descriptor rounded up to alignment*/ -int TxDescrSize; /* the size of a tx descriptor rounded up to alignment*/ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("BoardInitMem\n")); - - RxDescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; - pAC->RxDescrPerRing = RX_RING_SIZE / RxDescrSize; - TxDescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * DESCR_ALIGN; - pAC->TxDescrPerRing = TX_RING_SIZE / RxDescrSize; - - for (i=0; iGIni.GIMacsFound; i++) { - SetupRing( - pAC, - pAC->TxPort[i][0].pTxDescrRing, - pAC->TxPort[i][0].VTxDescrRing, - (RXD**)&pAC->TxPort[i][0].pTxdRingHead, - (RXD**)&pAC->TxPort[i][0].pTxdRingTail, - (RXD**)&pAC->TxPort[i][0].pTxdRingPrev, - &pAC->TxPort[i][0].TxdRingFree, - SK_TRUE); - SetupRing( - pAC, - pAC->RxPort[i].pRxDescrRing, - pAC->RxPort[i].VRxDescrRing, - &pAC->RxPort[i].pRxdRingHead, - &pAC->RxPort[i].pRxdRingTail, - &pAC->RxPort[i].pRxdRingPrev, - &pAC->RxPort[i].RxdRingFree, - SK_FALSE); - } -} /* BoardInitMem */ - - -/***************************************************************************** - * - * SetupRing - create one descriptor ring - * - * Description: - * This function creates one descriptor ring in the given memory area. - * The head, tail and number of free descriptors in the ring are set. - * - * Returns: - * none - */ -static void SetupRing( -SK_AC *pAC, -void *pMemArea, /* a pointer to the memory area for the ring */ -uintptr_t VMemArea, /* the virtual bus address of the memory area */ -RXD **ppRingHead, /* address where the head should be written */ -RXD **ppRingTail, /* address where the tail should be written */ -RXD **ppRingPrev, /* address where the tail should be written */ -int *pRingFree, /* address where the # of free descr. goes */ -SK_BOOL IsTx) /* flag: is this a tx ring */ -{ -int i; /* loop counter */ -int DescrSize; /* the size of a descriptor rounded up to alignment*/ -int DescrNum; /* number of descriptors per ring */ -RXD *pDescr; /* pointer to a descriptor (receive or transmit) */ -RXD *pNextDescr; /* pointer to the next descriptor */ -RXD *pPrevDescr; /* pointer to the previous descriptor */ -uintptr_t VNextDescr; /* the virtual bus address of the next descriptor */ - - if (IsTx == SK_TRUE) { - DescrSize = (((sizeof(TXD) - 1) / DESCR_ALIGN) + 1) * - DESCR_ALIGN; - DescrNum = TX_RING_SIZE / DescrSize; - } else { - DescrSize = (((sizeof(RXD) - 1) / DESCR_ALIGN) + 1) * - DESCR_ALIGN; - DescrNum = RX_RING_SIZE / DescrSize; - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, - ("Descriptor size: %d Descriptor Number: %d\n", - DescrSize,DescrNum)); - - pDescr = (RXD*) pMemArea; - pPrevDescr = NULL; - pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); - VNextDescr = VMemArea + DescrSize; - for(i=0; iVNextRxd = VNextDescr & 0xffffffffULL; - pDescr->pNextRxd = pNextDescr; - if (!IsTx) pDescr->TcpSumStarts = ETH_HLEN << 16 | ETH_HLEN; - - /* advance one step */ - pPrevDescr = pDescr; - pDescr = pNextDescr; - pNextDescr = (RXD*) (((char*)pDescr) + DescrSize); - VNextDescr += DescrSize; - } - pPrevDescr->pNextRxd = (RXD*) pMemArea; - pPrevDescr->VNextRxd = VMemArea; - pDescr = (RXD*) pMemArea; - *ppRingHead = (RXD*) pMemArea; - *ppRingTail = *ppRingHead; - *ppRingPrev = pPrevDescr; - *pRingFree = DescrNum; -} /* SetupRing */ - - -/***************************************************************************** - * - * PortReInitBmu - re-initiate the descriptor rings for one port - * - * Description: - * This function reinitializes the descriptor rings of one port - * in memory. The port must be stopped before. - * The HW is initialized with the descriptor start addresses. - * - * Returns: - * none - */ -static void PortReInitBmu( -SK_AC *pAC, /* pointer to adapter context */ -int PortIndex) /* index of the port for which to re-init */ -{ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("PortReInitBmu ")); - - /* set address of first descriptor of ring in BMU */ - SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_L, - (uint32_t)(((caddr_t) - (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + - pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) & - 0xFFFFFFFF)); - SK_OUT32(pAC->IoBase, TxQueueAddr[PortIndex][TX_PRIO_LOW]+ Q_DA_H, - (uint32_t)(((caddr_t) - (pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxdRingHead) - - pAC->TxPort[PortIndex][TX_PRIO_LOW].pTxDescrRing + - pAC->TxPort[PortIndex][TX_PRIO_LOW].VTxDescrRing) >> 32)); - SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_L, - (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - - pAC->RxPort[PortIndex].pRxDescrRing + - pAC->RxPort[PortIndex].VRxDescrRing) & 0xFFFFFFFF)); - SK_OUT32(pAC->IoBase, RxQueueAddr[PortIndex]+Q_DA_H, - (uint32_t)(((caddr_t)(pAC->RxPort[PortIndex].pRxdRingHead) - - pAC->RxPort[PortIndex].pRxDescrRing + - pAC->RxPort[PortIndex].VRxDescrRing) >> 32)); -} /* PortReInitBmu */ - - -/**************************************************************************** - * - * SkGeIsr - handle adapter interrupts - * - * Description: - * The interrupt routine is called when the network adapter - * generates an interrupt. It may also be called if another device - * shares this interrupt vector with the driver. - * - * Returns: N/A - * - */ -static SkIsrRetVar SkGeIsr(int irq, void *dev_id) -{ -struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; -DEV_NET *pNet; -SK_AC *pAC; -SK_U32 IntSrc; /* interrupts source register contents */ - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - /* - * Check and process if its our interrupt - */ - SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); - if (IntSrc == 0) { - return SkIsrRetNone; - } - - while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { -#if 0 /* software irq currently not used */ - if (IntSrc & IS_IRQ_SW) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("Software IRQ\n")); - } -#endif - if (IntSrc & IS_R1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX1 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 0); - } - if (IntSrc & IS_R2_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX2 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 1); - } -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IS_XA1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - } - if (IntSrc & IS_XA2_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX2 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[1][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[1][TX_PRIO_LOW].TxDesRingLock); - } -#if 0 /* only if sync. queues used */ - if (IntSrc & IS_XS1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 0, TX_PRIO_HIGH); - } - if (IntSrc & IS_XS2_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX2 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 1); - spin_lock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 1, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[1][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 1, TX_PRIO_HIGH); - } -#endif -#endif - - /* do all IO at once */ - if (IntSrc & IS_R1_F) - ClearAndStartRx(pAC, 0); - if (IntSrc & IS_R2_F) - ClearAndStartRx(pAC, 1); -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IS_XA1_F) - ClearTxIrq(pAC, 0, TX_PRIO_LOW); - if (IntSrc & IS_XA2_F) - ClearTxIrq(pAC, 1, TX_PRIO_LOW); -#endif - SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); - } /* while (IntSrc & IRQ_MASK != 0) */ - - IntSrc &= pAC->GIni.GIValIrqMask; - if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, - ("SPECIAL IRQ DP-Cards => %x\n", IntSrc)); - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - if (IntSrc & SPECIAL_IRQS) - SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - /* - * do it all again is case we cleared an interrupt that - * came in after handling the ring (OUTs may be delayed - * in hardware buffers, but are through after IN) - * - * rroesler: has been commented out and shifted to - * SkGeDrvEvent(), because it is timer - * guarded now - * - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - ReceiveIrq(pAC, &pAC->RxPort[1], SK_TRUE); - */ - - if (pAC->CheckQueue) { - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - - /* IRQ is processed - Enable IRQs again*/ - SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - - return SkIsrRetHandled; -} /* SkGeIsr */ - - -/**************************************************************************** - * - * SkGeIsrOnePort - handle adapter interrupts for single port adapter - * - * Description: - * The interrupt routine is called when the network adapter - * generates an interrupt. It may also be called if another device - * shares this interrupt vector with the driver. - * This is the same as above, but handles only one port. - * - * Returns: N/A - * - */ -static SkIsrRetVar SkGeIsrOnePort(int irq, void *dev_id) -{ -struct SK_NET_DEVICE *dev = (struct SK_NET_DEVICE *)dev_id; -DEV_NET *pNet; -SK_AC *pAC; -SK_U32 IntSrc; /* interrupts source register contents */ - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - /* - * Check and process if its our interrupt - */ - SK_IN32(pAC->IoBase, B0_SP_ISRC, &IntSrc); - if (IntSrc == 0) { - return SkIsrRetNone; - } - - while (((IntSrc & IRQ_MASK) & ~SPECIAL_IRQS) != 0) { -#if 0 /* software irq currently not used */ - if (IntSrc & IS_IRQ_SW) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("Software IRQ\n")); - } -#endif - if (IntSrc & IS_R1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF RX1 IRQ\n")); - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - SK_PNMI_CNT_RX_INTR(pAC, 0); - } -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IS_XA1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF AS TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - FreeTxDescriptors(pAC, &pAC->TxPort[0][TX_PRIO_LOW]); - spin_unlock(&pAC->TxPort[0][TX_PRIO_LOW].TxDesRingLock); - } -#if 0 /* only if sync. queues used */ - if (IntSrc & IS_XS1_F) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_INT_SRC, - ("EOF SY TX1 IRQ\n")); - SK_PNMI_CNT_TX_INTR(pAC, 0); - spin_lock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - FreeTxDescriptors(pAC, 0, TX_PRIO_HIGH); - spin_unlock(&pAC->TxPort[0][TX_PRIO_HIGH].TxDesRingLock); - ClearTxIrq(pAC, 0, TX_PRIO_HIGH); - } -#endif -#endif - - /* do all IO at once */ - if (IntSrc & IS_R1_F) - ClearAndStartRx(pAC, 0); -#ifdef USE_TX_COMPLETE /* only if tx complete interrupt used */ - if (IntSrc & IS_XA1_F) - ClearTxIrq(pAC, 0, TX_PRIO_LOW); -#endif - SK_IN32(pAC->IoBase, B0_ISRC, &IntSrc); - } /* while (IntSrc & IRQ_MASK != 0) */ - - IntSrc &= pAC->GIni.GIValIrqMask; - if ((IntSrc & SPECIAL_IRQS) || pAC->CheckQueue) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_INT_SRC, - ("SPECIAL IRQ SP-Cards => %x\n", IntSrc)); - pAC->CheckQueue = SK_FALSE; - spin_lock(&pAC->SlowPathLock); - if (IntSrc & SPECIAL_IRQS) - SkGeSirqIsr(pAC, pAC->IoBase, IntSrc); - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock(&pAC->SlowPathLock); - } - /* - * do it all again is case we cleared an interrupt that - * came in after handling the ring (OUTs may be delayed - * in hardware buffers, but are through after IN) - * - * rroesler: has been commented out and shifted to - * SkGeDrvEvent(), because it is timer - * guarded now - * - ReceiveIrq(pAC, &pAC->RxPort[0], SK_TRUE); - */ - - /* IRQ is processed - Enable IRQs again*/ - SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - - return SkIsrRetHandled; -} /* SkGeIsrOnePort */ - -#ifdef CONFIG_NET_POLL_CONTROLLER -/**************************************************************************** - * - * SkGePollController - polling receive, for netconsole - * - * Description: - * Polling receive - used by netconsole and other diagnostic tools - * to allow network i/o with interrupts disabled. - * - * Returns: N/A - */ -static void SkGePollController(struct net_device *dev) -{ - disable_irq(dev->irq); - SkGeIsr(dev->irq, dev); - enable_irq(dev->irq); -} -#endif - -/**************************************************************************** - * - * SkGeOpen - handle start of initialized adapter - * - * Description: - * This function starts the initialized adapter. - * The board level variable is set and the adapter is - * brought to full functionality. - * The device flags are set for operation. - * Do all necessary level 2 initialization, enable interrupts and - * give start command to RLMT. - * - * Returns: - * 0 on success - * != 0 on error - */ -static int SkGeOpen( -struct SK_NET_DEVICE *dev) -{ - DEV_NET *pNet; - SK_AC *pAC; - unsigned long Flags; /* for spin lock */ - int i; - SK_EVPARA EvPara; /* an event parameter union */ - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeOpen: pAC=0x%lX:\n", (unsigned long)pAC)); - -#ifdef SK_DIAG_SUPPORT - if (pAC->DiagModeActive == DIAG_ACTIVE) { - if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { - return (-1); /* still in use by diag; deny actions */ - } - } -#endif - - /* Set blink mode */ - if ((pAC->PciDev->vendor == 0x1186) || (pAC->PciDev->vendor == 0x11ab )) - pAC->GIni.GILedBlinkCtrl = OEM_CONFIG_VALUE; - - if (pAC->BoardLevel == SK_INIT_DATA) { - /* level 1 init common modules here */ - if (SkGeInit(pAC, pAC->IoBase, SK_INIT_IO) != 0) { - printk("%s: HWInit (1) failed.\n", pAC->dev[pNet->PortNr]->name); - return (-1); - } - SkI2cInit (pAC, pAC->IoBase, SK_INIT_IO); - SkEventInit (pAC, pAC->IoBase, SK_INIT_IO); - SkPnmiInit (pAC, pAC->IoBase, SK_INIT_IO); - SkAddrInit (pAC, pAC->IoBase, SK_INIT_IO); - SkRlmtInit (pAC, pAC->IoBase, SK_INIT_IO); - SkTimerInit (pAC, pAC->IoBase, SK_INIT_IO); - pAC->BoardLevel = SK_INIT_IO; - } - - if (pAC->BoardLevel != SK_INIT_RUN) { - /* tschilling: Level 2 init modules here, check return value. */ - if (SkGeInit(pAC, pAC->IoBase, SK_INIT_RUN) != 0) { - printk("%s: HWInit (2) failed.\n", pAC->dev[pNet->PortNr]->name); - return (-1); - } - SkI2cInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkEventInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkPnmiInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkAddrInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkRlmtInit (pAC, pAC->IoBase, SK_INIT_RUN); - SkTimerInit (pAC, pAC->IoBase, SK_INIT_RUN); - pAC->BoardLevel = SK_INIT_RUN; - } - - for (i=0; iGIni.GIMacsFound; i++) { - /* Enable transmit descriptor polling. */ - SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); - FillRxRing(pAC, &pAC->RxPort[i]); - } - SkGeYellowLED(pAC, pAC->IoBase, 1); - - StartDrvCleanupTimer(pAC); - SkDimEnableModerationIfNeeded(pAC); - SkDimDisplayModerationSettings(pAC); - - pAC->GIni.GIValIrqMask &= IRQ_MASK; - - /* enable Interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - if ((pAC->RlmtMode != 0) && (pAC->MaxPorts == 0)) { - EvPara.Para32[0] = pAC->RlmtNets; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, - EvPara); - EvPara.Para32[0] = pAC->RlmtMode; - EvPara.Para32[1] = 0; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_MODE_CHANGE, - EvPara); - } - - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - pAC->MaxPorts++; - - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeOpen suceeded\n")); - - return (0); -} /* SkGeOpen */ - - -/**************************************************************************** - * - * SkGeClose - Stop initialized adapter - * - * Description: - * Close initialized adapter. - * - * Returns: - * 0 - on success - * error code - on error - */ -static int SkGeClose( -struct SK_NET_DEVICE *dev) -{ - DEV_NET *pNet; - DEV_NET *newPtrNet; - SK_AC *pAC; - - unsigned long Flags; /* for spin lock */ - int i; - int PortIdx; - SK_EVPARA EvPara; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeClose: pAC=0x%lX ", (unsigned long)pAC)); - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - -#ifdef SK_DIAG_SUPPORT - if (pAC->DiagModeActive == DIAG_ACTIVE) { - if (pAC->DiagFlowCtrl == SK_FALSE) { - /* - ** notify that the interface which has been closed - ** by operator interaction must not be started up - ** again when the DIAG has finished. - */ - newPtrNet = netdev_priv(pAC->dev[0]); - if (newPtrNet == pNet) { - pAC->WasIfUp[0] = SK_FALSE; - } else { - pAC->WasIfUp[1] = SK_FALSE; - } - return 0; /* return to system everything is fine... */ - } else { - pAC->DiagFlowCtrl = SK_FALSE; - } - } -#endif - - netif_stop_queue(dev); - - if (pAC->RlmtNets == 1) - PortIdx = pAC->ActivePort; - else - PortIdx = pNet->NetNr; - - StopDrvCleanupTimer(pAC); - - /* - * Clear multicast table, promiscuous mode .... - */ - SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_NONE); - - if (pAC->MaxPorts == 1) { - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - /* stop the hardware */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = SK_INIT_DATA; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - } else { - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = pNet->NetNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkPnmiEvent(pAC, pAC->IoBase, SK_PNMI_EVT_XMAC_RESET, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - /* Stop port */ - spin_lock_irqsave(&pAC->TxPort[pNet->PortNr] - [TX_PRIO_LOW].TxDesRingLock, Flags); - SkGeStopPort(pAC, pAC->IoBase, pNet->PortNr, - SK_STOP_ALL, SK_HARD_RST); - spin_unlock_irqrestore(&pAC->TxPort[pNet->PortNr] - [TX_PRIO_LOW].TxDesRingLock, Flags); - } - - if (pAC->RlmtNets == 1) { - /* clear all descriptor rings */ - for (i=0; iGIni.GIMacsFound; i++) { - ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[i]); - ClearTxRing(pAC, &pAC->TxPort[i][TX_PRIO_LOW]); - } - } else { - /* clear port descriptor rings */ - ReceiveIrq(pAC, &pAC->RxPort[pNet->PortNr], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[pNet->PortNr]); - ClearTxRing(pAC, &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW]); - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeClose: done ")); - - SK_MEMSET(&(pAC->PnmiBackup), 0, sizeof(SK_PNMI_STRUCT_DATA)); - SK_MEMCPY(&(pAC->PnmiBackup), &(pAC->PnmiStruct), - sizeof(SK_PNMI_STRUCT_DATA)); - - pAC->MaxPorts--; - - return (0); -} /* SkGeClose */ - - -/***************************************************************************** - * - * SkGeXmit - Linux frame transmit function - * - * Description: - * The system calls this function to send frames onto the wire. - * It puts the frame in the tx descriptor ring. If the ring is - * full then, the 'tbusy' flag is set. - * - * Returns: - * 0, if everything is ok - * !=0, on error - * WARNING: returning 1 in 'tbusy' case caused system crashes (double - * allocated skb's) !!! - */ -static int SkGeXmit(struct sk_buff *skb, struct SK_NET_DEVICE *dev) -{ -DEV_NET *pNet; -SK_AC *pAC; -int Rc; /* return code of XmitFrame */ - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - if ((!skb_shinfo(skb)->nr_frags) || - (pAC->GIni.GIChipId == CHIP_ID_GENESIS)) { - /* Don't activate scatter-gather and hardware checksum */ - - if (pAC->RlmtNets == 2) - Rc = XmitFrame( - pAC, - &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], - skb); - else - Rc = XmitFrame( - pAC, - &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], - skb); - } else { - /* scatter-gather and hardware TCP checksumming anabled*/ - if (pAC->RlmtNets == 2) - Rc = XmitFrameSG( - pAC, - &pAC->TxPort[pNet->PortNr][TX_PRIO_LOW], - skb); - else - Rc = XmitFrameSG( - pAC, - &pAC->TxPort[pAC->ActivePort][TX_PRIO_LOW], - skb); - } - - /* Transmitter out of resources? */ - if (Rc <= 0) { - netif_stop_queue(dev); - } - - /* If not taken, give buffer ownership back to the - * queueing layer. - */ - if (Rc < 0) - return (1); - - dev->trans_start = jiffies; - return (0); -} /* SkGeXmit */ - - -/***************************************************************************** - * - * XmitFrame - fill one socket buffer into the transmit ring - * - * Description: - * This function puts a message into the transmit descriptor ring - * if there is a descriptors left. - * Linux skb's consist of only one continuous buffer. - * The first step locks the ring. It is held locked - * all time to avoid problems with SWITCH_../PORT_RESET. - * Then the descriptoris allocated. - * The second part is linking the buffer to the descriptor. - * At the very last, the Control field of the descriptor - * is made valid for the BMU and a start TX command is given - * if necessary. - * - * Returns: - * > 0 - on succes: the number of bytes in the message - * = 0 - on resource shortage: this frame sent or dropped, now - * the ring is full ( -> set tbusy) - * < 0 - on failure: other problems ( -> return failure to upper layers) - */ -static int XmitFrame( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort, /* pointer to struct of port to send to */ -struct sk_buff *pMessage) /* pointer to send-message */ -{ - TXD *pTxd; /* the rxd to fill */ - TXD *pOldTxd; - unsigned long Flags; - SK_U64 PhysAddr; - int BytesSend = pMessage->len; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_TX_PROGRESS, ("X")); - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); -#ifndef USE_TX_COMPLETE - FreeTxDescriptors(pAC, pTxPort); -#endif - if (pTxPort->TxdRingFree == 0) { - /* - ** no enough free descriptors in ring at the moment. - ** Maybe free'ing some old one help? - */ - FreeTxDescriptors(pAC, pTxPort); - if (pTxPort->TxdRingFree == 0) { - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_TX_PROGRESS, - ("XmitFrame failed\n")); - /* - ** the desired message can not be sent - ** Because tbusy seems to be set, the message - ** should not be freed here. It will be used - ** by the scheduler of the ethernet handler - */ - return (-1); - } - } - - /* - ** If the passed socket buffer is of smaller MTU-size than 60, - ** copy everything into new buffer and fill all bytes between - ** the original packet end and the new packet end of 60 with 0x00. - ** This is to resolve faulty padding by the HW with 0xaa bytes. - */ - if (BytesSend < C_LEN_ETHERNET_MINSIZE) { - if (skb_padto(pMessage, C_LEN_ETHERNET_MINSIZE)) { - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - return 0; - } - pMessage->len = C_LEN_ETHERNET_MINSIZE; - } - - /* - ** advance head counter behind descriptor needed for this frame, - ** so that needed descriptor is reserved from that on. The next - ** action will be to add the passed buffer to the TX-descriptor - */ - pTxd = pTxPort->pTxdRingHead; - pTxPort->pTxdRingHead = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - -#ifdef SK_DUMP_TX - DumpMsg(pMessage, "XmitFrame"); -#endif - - /* - ** First step is to map the data to be sent via the adapter onto - ** the DMA memory. Kernel 2.2 uses virt_to_bus(), but kernels 2.4 - ** and 2.6 need to use pci_map_page() for that mapping. - */ - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMessage->data), - ((unsigned long) pMessage->data & ~PAGE_MASK), - pMessage->len, - PCI_DMA_TODEVICE); - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pTxd->pMBuf = pMessage; - - if (pMessage->ip_summed == CHECKSUM_PARTIAL) { - u16 hdrlen = skb_transport_offset(pMessage); - u16 offset = hdrlen + pMessage->csum_offset; - - if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) && - (pAC->GIni.GIChipRev == 0) && - (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { - pTxd->TBControl = BMU_TCP_CHECK; - } else { - pTxd->TBControl = BMU_UDP_CHECK; - } - - pTxd->TcpSumOfs = 0; - pTxd->TcpSumSt = hdrlen; - pTxd->TcpSumWr = offset; - - pTxd->TBControl |= BMU_OWN | BMU_STF | - BMU_SW | BMU_EOF | -#ifdef USE_TX_COMPLETE - BMU_IRQ_EOF | -#endif - pMessage->len; - } else { - pTxd->TBControl = BMU_OWN | BMU_STF | BMU_CHECK | - BMU_SW | BMU_EOF | -#ifdef USE_TX_COMPLETE - BMU_IRQ_EOF | -#endif - pMessage->len; - } - - /* - ** If previous descriptor already done, give TX start cmd - */ - pOldTxd = xchg(&pTxPort->pTxdRingPrev, pTxd); - if ((pOldTxd->TBControl & BMU_OWN) == 0) { - SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START); - } - - /* - ** after releasing the lock, the skb may immediately be free'd - */ - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - if (pTxPort->TxdRingFree != 0) { - return (BytesSend); - } else { - return (0); - } - -} /* XmitFrame */ - -/***************************************************************************** - * - * XmitFrameSG - fill one socket buffer into the transmit ring - * (use SG and TCP/UDP hardware checksumming) - * - * Description: - * This function puts a message into the transmit descriptor ring - * if there is a descriptors left. - * - * Returns: - * > 0 - on succes: the number of bytes in the message - * = 0 - on resource shortage: this frame sent or dropped, now - * the ring is full ( -> set tbusy) - * < 0 - on failure: other problems ( -> return failure to upper layers) - */ -static int XmitFrameSG( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort, /* pointer to struct of port to send to */ -struct sk_buff *pMessage) /* pointer to send-message */ -{ - - TXD *pTxd; - TXD *pTxdFst; - TXD *pTxdLst; - int CurrFrag; - int BytesSend; - skb_frag_t *sk_frag; - SK_U64 PhysAddr; - unsigned long Flags; - SK_U32 Control; - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); -#ifndef USE_TX_COMPLETE - FreeTxDescriptors(pAC, pTxPort); -#endif - if ((skb_shinfo(pMessage)->nr_frags +1) > pTxPort->TxdRingFree) { - FreeTxDescriptors(pAC, pTxPort); - if ((skb_shinfo(pMessage)->nr_frags + 1) > pTxPort->TxdRingFree) { - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - SK_PNMI_CNT_NO_TX_BUF(pAC, pTxPort->PortIndex); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_TX_PROGRESS, - ("XmitFrameSG failed - Ring full\n")); - /* this message can not be sent now */ - return(-1); - } - } - - pTxd = pTxPort->pTxdRingHead; - pTxdFst = pTxd; - pTxdLst = pTxd; - BytesSend = 0; - - /* - ** Map the first fragment (header) into the DMA-space - */ - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMessage->data), - ((unsigned long) pMessage->data & ~PAGE_MASK), - skb_headlen(pMessage), - PCI_DMA_TODEVICE); - - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - - /* - ** Does the HW need to evaluate checksum for TCP or UDP packets? - */ - if (pMessage->ip_summed == CHECKSUM_PARTIAL) { - u16 hdrlen = skb_transport_offset(pMessage); - u16 offset = hdrlen + pMessage->csum_offset; - - Control = BMU_STFWD; - - /* - ** We have to use the opcode for tcp here, because the - ** opcode for udp is not working in the hardware yet - ** (Revision 2.0) - */ - if ((ipip_hdr(pMessage)->protocol == IPPROTO_UDP) && - (pAC->GIni.GIChipRev == 0) && - (pAC->GIni.GIChipId == CHIP_ID_YUKON)) { - Control |= BMU_TCP_CHECK; - } else { - Control |= BMU_UDP_CHECK; - } - - pTxd->TcpSumOfs = 0; - pTxd->TcpSumSt = hdrlen; - pTxd->TcpSumWr = offset; - } else - Control = BMU_CHECK | BMU_SW; - - pTxd->TBControl = BMU_STF | Control | skb_headlen(pMessage); - - pTxd = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - BytesSend += skb_headlen(pMessage); - - /* - ** Browse over all SG fragments and map each of them into the DMA space - */ - for (CurrFrag = 0; CurrFrag < skb_shinfo(pMessage)->nr_frags; CurrFrag++) { - sk_frag = &skb_shinfo(pMessage)->frags[CurrFrag]; - /* - ** we already have the proper value in entry - */ - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - sk_frag->page, - sk_frag->page_offset, - sk_frag->size, - PCI_DMA_TODEVICE); - - pTxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pTxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pTxd->pMBuf = pMessage; - - pTxd->TBControl = Control | BMU_OWN | sk_frag->size; - - /* - ** Do we have the last fragment? - */ - if( (CurrFrag+1) == skb_shinfo(pMessage)->nr_frags ) { -#ifdef USE_TX_COMPLETE - pTxd->TBControl |= BMU_EOF | BMU_IRQ_EOF; -#else - pTxd->TBControl |= BMU_EOF; -#endif - pTxdFst->TBControl |= BMU_OWN | BMU_SW; - } - pTxdLst = pTxd; - pTxd = pTxd->pNextTxd; - pTxPort->TxdRingFree--; - BytesSend += sk_frag->size; - } - - /* - ** If previous descriptor already done, give TX start cmd - */ - if ((pTxPort->pTxdRingPrev->TBControl & BMU_OWN) == 0) { - SK_OUT8(pTxPort->HwAddr, Q_CSR, CSR_START); - } - - pTxPort->pTxdRingPrev = pTxdLst; - pTxPort->pTxdRingHead = pTxd; - - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); - - if (pTxPort->TxdRingFree > 0) { - return (BytesSend); - } else { - return (0); - } -} - -/***************************************************************************** - * - * FreeTxDescriptors - release descriptors from the descriptor ring - * - * Description: - * This function releases descriptors from a transmit ring if they - * have been sent by the BMU. - * If a descriptors is sent, it can be freed and the message can - * be freed, too. - * The SOFTWARE controllable bit is used to prevent running around a - * completely free ring for ever. If this bit is no set in the - * frame (by XmitFrame), this frame has never been sent or is - * already freed. - * The Tx descriptor ring lock must be held while calling this function !!! - * - * Returns: - * none - */ -static void FreeTxDescriptors( -SK_AC *pAC, /* pointer to the adapter context */ -TX_PORT *pTxPort) /* pointer to destination port structure */ -{ -TXD *pTxd; /* pointer to the checked descriptor */ -TXD *pNewTail; /* pointer to 'end' of the ring */ -SK_U32 Control; /* TBControl field of descriptor */ -SK_U64 PhysAddr; /* address of DMA mapping */ - - pNewTail = pTxPort->pTxdRingTail; - pTxd = pNewTail; - /* - ** loop forever; exits if BMU_SW bit not set in start frame - ** or BMU_OWN bit set in any frame - */ - while (1) { - Control = pTxd->TBControl; - if ((Control & BMU_SW) == 0) { - /* - ** software controllable bit is set in first - ** fragment when given to BMU. Not set means that - ** this fragment was never sent or is already - ** freed ( -> ring completely free now). - */ - pTxPort->pTxdRingTail = pTxd; - netif_wake_queue(pAC->dev[pTxPort->PortIndex]); - return; - } - if (Control & BMU_OWN) { - pTxPort->pTxdRingTail = pTxd; - if (pTxPort->TxdRingFree > 0) { - netif_wake_queue(pAC->dev[pTxPort->PortIndex]); - } - return; - } - - /* - ** release the DMA mapping, because until not unmapped - ** this buffer is considered being under control of the - ** adapter card! - */ - PhysAddr = ((SK_U64) pTxd->VDataHigh) << (SK_U64) 32; - PhysAddr |= (SK_U64) pTxd->VDataLow; - pci_unmap_page(pAC->PciDev, PhysAddr, - pTxd->pMBuf->len, - PCI_DMA_TODEVICE); - - if (Control & BMU_EOF) - DEV_KFREE_SKB_ANY(pTxd->pMBuf); /* free message */ - - pTxPort->TxdRingFree++; - pTxd->TBControl &= ~BMU_SW; - pTxd = pTxd->pNextTxd; /* point behind fragment with EOF */ - } /* while(forever) */ -} /* FreeTxDescriptors */ - -/***************************************************************************** - * - * FillRxRing - fill the receive ring with valid descriptors - * - * Description: - * This function fills the receive ring descriptors with data - * segments and makes them valid for the BMU. - * The active ring is filled completely, if possible. - * The non-active ring is filled only partial to save memory. - * - * Description of rx ring structure: - * head - points to the descriptor which will be used next by the BMU - * tail - points to the next descriptor to give to the BMU - * - * Returns: N/A - */ -static void FillRxRing( -SK_AC *pAC, /* pointer to the adapter context */ -RX_PORT *pRxPort) /* ptr to port struct for which the ring - should be filled */ -{ -unsigned long Flags; - - spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); - while (pRxPort->RxdRingFree > pRxPort->RxFillLimit) { - if(!FillRxDescriptor(pAC, pRxPort)) - break; - } - spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); -} /* FillRxRing */ - - -/***************************************************************************** - * - * FillRxDescriptor - fill one buffer into the receive ring - * - * Description: - * The function allocates a new receive buffer and - * puts it into the next descriptor. - * - * Returns: - * SK_TRUE - a buffer was added to the ring - * SK_FALSE - a buffer could not be added - */ -static SK_BOOL FillRxDescriptor( -SK_AC *pAC, /* pointer to the adapter context struct */ -RX_PORT *pRxPort) /* ptr to port struct of ring to fill */ -{ -struct sk_buff *pMsgBlock; /* pointer to a new message block */ -RXD *pRxd; /* the rxd to fill */ -SK_U16 Length; /* data fragment length */ -SK_U64 PhysAddr; /* physical address of a rx buffer */ - - pMsgBlock = alloc_skb(pAC->RxBufSize, GFP_ATOMIC); - if (pMsgBlock == NULL) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_ENTRY, - ("%s: Allocation of rx buffer failed !\n", - pAC->dev[pRxPort->PortIndex]->name)); - SK_PNMI_CNT_NO_RX_BUF(pAC, pRxPort->PortIndex); - return(SK_FALSE); - } - skb_reserve(pMsgBlock, 2); /* to align IP frames */ - /* skb allocated ok, so add buffer */ - pRxd = pRxPort->pRxdRingTail; - pRxPort->pRxdRingTail = pRxd->pNextRxd; - pRxPort->RxdRingFree--; - Length = pAC->RxBufSize; - PhysAddr = (SK_U64) pci_map_page(pAC->PciDev, - virt_to_page(pMsgBlock->data), - ((unsigned long) pMsgBlock->data & - ~PAGE_MASK), - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - - pRxd->VDataLow = (SK_U32) (PhysAddr & 0xffffffff); - pRxd->VDataHigh = (SK_U32) (PhysAddr >> 32); - pRxd->pMBuf = pMsgBlock; - pRxd->RBControl = BMU_OWN | - BMU_STF | - BMU_IRQ_EOF | - BMU_TCP_CHECK | - Length; - return (SK_TRUE); - -} /* FillRxDescriptor */ - - -/***************************************************************************** - * - * ReQueueRxBuffer - fill one buffer back into the receive ring - * - * Description: - * Fill a given buffer back into the rx ring. The buffer - * has been previously allocated and aligned, and its phys. - * address calculated, so this is no more necessary. - * - * Returns: N/A - */ -static void ReQueueRxBuffer( -SK_AC *pAC, /* pointer to the adapter context struct */ -RX_PORT *pRxPort, /* ptr to port struct of ring to fill */ -struct sk_buff *pMsg, /* pointer to the buffer */ -SK_U32 PhysHigh, /* phys address high dword */ -SK_U32 PhysLow) /* phys address low dword */ -{ -RXD *pRxd; /* the rxd to fill */ -SK_U16 Length; /* data fragment length */ - - pRxd = pRxPort->pRxdRingTail; - pRxPort->pRxdRingTail = pRxd->pNextRxd; - pRxPort->RxdRingFree--; - Length = pAC->RxBufSize; - - pRxd->VDataLow = PhysLow; - pRxd->VDataHigh = PhysHigh; - pRxd->pMBuf = pMsg; - pRxd->RBControl = BMU_OWN | - BMU_STF | - BMU_IRQ_EOF | - BMU_TCP_CHECK | - Length; - return; -} /* ReQueueRxBuffer */ - -/***************************************************************************** - * - * ReceiveIrq - handle a receive IRQ - * - * Description: - * This function is called when a receive IRQ is set. - * It walks the receive descriptor ring and sends up all - * frames that are complete. - * - * Returns: N/A - */ -static void ReceiveIrq( - SK_AC *pAC, /* pointer to adapter context */ - RX_PORT *pRxPort, /* pointer to receive port struct */ - SK_BOOL SlowPathLock) /* indicates if SlowPathLock is needed */ -{ -RXD *pRxd; /* pointer to receive descriptors */ -SK_U32 Control; /* control field of descriptor */ -struct sk_buff *pMsg; /* pointer to message holding frame */ -struct sk_buff *pNewMsg; /* pointer to a new message for copying frame */ -int FrameLength; /* total length of received frame */ -SK_MBUF *pRlmtMbuf; /* ptr to a buffer for giving a frame to rlmt */ -SK_EVPARA EvPara; /* an event parameter union */ -unsigned long Flags; /* for spin lock */ -int PortIndex = pRxPort->PortIndex; -unsigned int Offset; -unsigned int NumBytes; -unsigned int ForRlmt; -SK_BOOL IsBc; -SK_BOOL IsMc; -SK_BOOL IsBadFrame; /* Bad frame */ - -SK_U32 FrameStat; -SK_U64 PhysAddr; - -rx_start: - /* do forever; exit if BMU_OWN found */ - for ( pRxd = pRxPort->pRxdRingHead ; - pRxPort->RxdRingFree < pAC->RxDescrPerRing ; - pRxd = pRxd->pNextRxd, - pRxPort->pRxdRingHead = pRxd, - pRxPort->RxdRingFree ++) { - - /* - * For a better understanding of this loop - * Go through every descriptor beginning at the head - * Please note: the ring might be completely received so the OWN bit - * set is not a good crirteria to leave that loop. - * Therefore the RingFree counter is used. - * On entry of this loop pRxd is a pointer to the Rxd that needs - * to be checked next. - */ - - Control = pRxd->RBControl; - - /* check if this descriptor is ready */ - if ((Control & BMU_OWN) != 0) { - /* this descriptor is not yet ready */ - /* This is the usual end of the loop */ - /* We don't need to start the ring again */ - FillRxRing(pAC, pRxPort); - return; - } - pAC->DynIrqModInfo.NbrProcessedDescr++; - - /* get length of frame and check it */ - FrameLength = Control & BMU_BBC; - if (FrameLength > pAC->RxBufSize) { - goto rx_failed; - } - - /* check for STF and EOF */ - if ((Control & (BMU_STF | BMU_EOF)) != (BMU_STF | BMU_EOF)) { - goto rx_failed; - } - - /* here we have a complete frame in the ring */ - pMsg = pRxd->pMBuf; - - FrameStat = pRxd->FrameStat; - - /* check for frame length mismatch */ -#define XMR_FS_LEN_SHIFT 18 -#define GMR_FS_LEN_SHIFT 16 - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - if (FrameLength != (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT)) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Frame length mismatch (%u/%u).\n", - FrameLength, - (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); - goto rx_failed; - } - } - else { - if (FrameLength != (SK_U32) (FrameStat >> GMR_FS_LEN_SHIFT)) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Frame length mismatch (%u/%u).\n", - FrameLength, - (SK_U32) (FrameStat >> XMR_FS_LEN_SHIFT))); - goto rx_failed; - } - } - - /* Set Rx Status */ - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - IsBc = (FrameStat & XMR_FS_BC) != 0; - IsMc = (FrameStat & XMR_FS_MC) != 0; - IsBadFrame = (FrameStat & - (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0; - } else { - IsBc = (FrameStat & GMR_FS_BC) != 0; - IsMc = (FrameStat & GMR_FS_MC) != 0; - IsBadFrame = (((FrameStat & GMR_FS_ANY_ERR) != 0) || - ((FrameStat & GMR_FS_RX_OK) == 0)); - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, - ("Received frame of length %d on port %d\n", - FrameLength, PortIndex)); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 0, - ("Number of free rx descriptors: %d\n", - pRxPort->RxdRingFree)); -/* DumpMsg(pMsg, "Rx"); */ - - if ((Control & BMU_STAT_VAL) != BMU_STAT_VAL || (IsBadFrame)) { -#if 0 - (FrameStat & (XMR_FS_ANY_ERR | XMR_FS_2L_VLAN)) != 0) { -#endif - /* there is a receive error in this frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("skge: Error in received frame, dropped!\n" - "Control: %x\nRxStat: %x\n", - Control, FrameStat)); - - ReQueueRxBuffer(pAC, pRxPort, pMsg, - pRxd->VDataHigh, pRxd->VDataLow); - - continue; - } - - /* - * if short frame then copy data to reduce memory waste - */ - if ((FrameLength < SK_COPY_THRESHOLD) && - ((pNewMsg = alloc_skb(FrameLength+2, GFP_ATOMIC)) != NULL)) { - /* - * Short frame detected and allocation successfull - */ - /* use new skb and copy data */ - skb_reserve(pNewMsg, 2); - skb_put(pNewMsg, FrameLength); - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - - pci_dma_sync_single_for_cpu(pAC->PciDev, - (dma_addr_t) PhysAddr, - FrameLength, - PCI_DMA_FROMDEVICE); - skb_copy_to_linear_data(pNewMsg, pMsg, FrameLength); - - pci_dma_sync_single_for_device(pAC->PciDev, - (dma_addr_t) PhysAddr, - FrameLength, - PCI_DMA_FROMDEVICE); - ReQueueRxBuffer(pAC, pRxPort, pMsg, - pRxd->VDataHigh, pRxd->VDataLow); - - pMsg = pNewMsg; - - } - else { - /* - * if large frame, or SKB allocation failed, pass - * the SKB directly to the networking - */ - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - - /* release the DMA mapping */ - pci_unmap_single(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - - /* set length in message */ - skb_put(pMsg, FrameLength); - } /* frame > SK_COPY_TRESHOLD */ - -#ifdef USE_SK_RX_CHECKSUM - pMsg->csum = pRxd->TcpSums & 0xffff; - pMsg->ip_summed = CHECKSUM_COMPLETE; -#else - pMsg->ip_summed = CHECKSUM_NONE; -#endif - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("V")); - ForRlmt = SK_RLMT_RX_PROTOCOL; -#if 0 - IsBc = (FrameStat & XMR_FS_BC)==XMR_FS_BC; -#endif - SK_RLMT_PRE_LOOKAHEAD(pAC, PortIndex, FrameLength, - IsBc, &Offset, &NumBytes); - if (NumBytes != 0) { -#if 0 - IsMc = (FrameStat & XMR_FS_MC)==XMR_FS_MC; -#endif - SK_RLMT_LOOKAHEAD(pAC, PortIndex, - &pMsg->data[Offset], - IsBc, IsMc, &ForRlmt); - } - if (ForRlmt == SK_RLMT_RX_PROTOCOL) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("W")); - /* send up only frames from active port */ - if ((PortIndex == pAC->ActivePort) || - (pAC->RlmtNets == 2)) { - /* frame for upper layer */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, 1,("U")); -#ifdef xDEBUG - DumpMsg(pMsg, "Rx"); -#endif - SK_PNMI_CNT_RX_OCTETS_DELIVERED(pAC, - FrameLength, pRxPort->PortIndex); - - pMsg->protocol = eth_type_trans(pMsg, - pAC->dev[pRxPort->PortIndex]); - netif_rx(pMsg); - pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; - } - else { - /* drop frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("D")); - DEV_KFREE_SKB(pMsg); - } - - } /* if not for rlmt */ - else { - /* packet for rlmt */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, ("R")); - pRlmtMbuf = SkDrvAllocRlmtMbuf(pAC, - pAC->IoBase, FrameLength); - if (pRlmtMbuf != NULL) { - pRlmtMbuf->pNext = NULL; - pRlmtMbuf->Length = FrameLength; - pRlmtMbuf->PortIdx = PortIndex; - EvPara.pParaPtr = pRlmtMbuf; - memcpy((char*)(pRlmtMbuf->pData), - (char*)(pMsg->data), - FrameLength); - - /* SlowPathLock needed? */ - if (SlowPathLock == SK_TRUE) { - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - SkEventQueue(pAC, SKGE_RLMT, - SK_RLMT_PACKET_RECEIVED, - EvPara); - pAC->CheckQueue = SK_TRUE; - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - } else { - SkEventQueue(pAC, SKGE_RLMT, - SK_RLMT_PACKET_RECEIVED, - EvPara); - pAC->CheckQueue = SK_TRUE; - } - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, - SK_DBGCAT_DRV_RX_PROGRESS, - ("Q")); - } - if ((pAC->dev[pRxPort->PortIndex]->flags & - (IFF_PROMISC | IFF_ALLMULTI)) != 0 || - (ForRlmt & SK_RLMT_RX_PROTOCOL) == - SK_RLMT_RX_PROTOCOL) { - pMsg->protocol = eth_type_trans(pMsg, - pAC->dev[pRxPort->PortIndex]); - netif_rx(pMsg); - pAC->dev[pRxPort->PortIndex]->last_rx = jiffies; - } - else { - DEV_KFREE_SKB(pMsg); - } - - } /* if packet for rlmt */ - } /* for ... scanning the RXD ring */ - - /* RXD ring is empty -> fill and restart */ - FillRxRing(pAC, pRxPort); - /* do not start if called from Close */ - if (pAC->BoardLevel > SK_INIT_DATA) { - ClearAndStartRx(pAC, PortIndex); - } - return; - -rx_failed: - /* remove error frame */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ERROR, - ("Schrottdescriptor, length: 0x%x\n", FrameLength)); - - /* release the DMA mapping */ - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - pci_unmap_page(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - DEV_KFREE_SKB_IRQ(pRxd->pMBuf); - pRxd->pMBuf = NULL; - pRxPort->RxdRingFree++; - pRxPort->pRxdRingHead = pRxd->pNextRxd; - goto rx_start; - -} /* ReceiveIrq */ - - -/***************************************************************************** - * - * ClearAndStartRx - give a start receive command to BMU, clear IRQ - * - * Description: - * This function sends a start command and a clear interrupt - * command for one receive queue to the BMU. - * - * Returns: N/A - * none - */ -static void ClearAndStartRx( -SK_AC *pAC, /* pointer to the adapter context */ -int PortIndex) /* index of the receive port (XMAC) */ -{ - SK_OUT8(pAC->IoBase, - RxQueueAddr[PortIndex]+Q_CSR, - CSR_START | CSR_IRQ_CL_F); -} /* ClearAndStartRx */ - - -/***************************************************************************** - * - * ClearTxIrq - give a clear transmit IRQ command to BMU - * - * Description: - * This function sends a clear tx IRQ command for one - * transmit queue to the BMU. - * - * Returns: N/A - */ -static void ClearTxIrq( -SK_AC *pAC, /* pointer to the adapter context */ -int PortIndex, /* index of the transmit port (XMAC) */ -int Prio) /* priority or normal queue */ -{ - SK_OUT8(pAC->IoBase, - TxQueueAddr[PortIndex][Prio]+Q_CSR, - CSR_IRQ_CL_F); -} /* ClearTxIrq */ - - -/***************************************************************************** - * - * ClearRxRing - remove all buffers from the receive ring - * - * Description: - * This function removes all receive buffers from the ring. - * The receive BMU must be stopped before calling this function. - * - * Returns: N/A - */ -static void ClearRxRing( -SK_AC *pAC, /* pointer to adapter context */ -RX_PORT *pRxPort) /* pointer to rx port struct */ -{ -RXD *pRxd; /* pointer to the current descriptor */ -unsigned long Flags; -SK_U64 PhysAddr; - - if (pRxPort->RxdRingFree == pAC->RxDescrPerRing) { - return; - } - spin_lock_irqsave(&pRxPort->RxDesRingLock, Flags); - pRxd = pRxPort->pRxdRingHead; - do { - if (pRxd->pMBuf != NULL) { - - PhysAddr = ((SK_U64) pRxd->VDataHigh) << (SK_U64)32; - PhysAddr |= (SK_U64) pRxd->VDataLow; - pci_unmap_page(pAC->PciDev, - PhysAddr, - pAC->RxBufSize - 2, - PCI_DMA_FROMDEVICE); - DEV_KFREE_SKB(pRxd->pMBuf); - pRxd->pMBuf = NULL; - } - pRxd->RBControl &= BMU_OWN; - pRxd = pRxd->pNextRxd; - pRxPort->RxdRingFree++; - } while (pRxd != pRxPort->pRxdRingTail); - pRxPort->pRxdRingTail = pRxPort->pRxdRingHead; - spin_unlock_irqrestore(&pRxPort->RxDesRingLock, Flags); -} /* ClearRxRing */ - -/***************************************************************************** - * - * ClearTxRing - remove all buffers from the transmit ring - * - * Description: - * This function removes all transmit buffers from the ring. - * The transmit BMU must be stopped before calling this function - * and transmitting at the upper level must be disabled. - * The BMU own bit of all descriptors is cleared, the rest is - * done by calling FreeTxDescriptors. - * - * Returns: N/A - */ -static void ClearTxRing( -SK_AC *pAC, /* pointer to adapter context */ -TX_PORT *pTxPort) /* pointer to tx prt struct */ -{ -TXD *pTxd; /* pointer to the current descriptor */ -int i; -unsigned long Flags; - - spin_lock_irqsave(&pTxPort->TxDesRingLock, Flags); - pTxd = pTxPort->pTxdRingHead; - for (i=0; iTxDescrPerRing; i++) { - pTxd->TBControl &= ~BMU_OWN; - pTxd = pTxd->pNextTxd; - } - FreeTxDescriptors(pAC, pTxPort); - spin_unlock_irqrestore(&pTxPort->TxDesRingLock, Flags); -} /* ClearTxRing */ - -/***************************************************************************** - * - * SkGeSetMacAddr - Set the hardware MAC address - * - * Description: - * This function sets the MAC address used by the adapter. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeSetMacAddr(struct SK_NET_DEVICE *dev, void *p) -{ - -DEV_NET *pNet = netdev_priv(dev); -SK_AC *pAC = pNet->pAC; - -struct sockaddr *addr = p; -unsigned long Flags; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeSetMacAddr starts now...\n")); - if(netif_running(dev)) - return -EBUSY; - - memcpy(dev->dev_addr, addr->sa_data,dev->addr_len); - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - if (pAC->RlmtNets == 2) - SkAddrOverride(pAC, pAC->IoBase, pNet->NetNr, - (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); - else - SkAddrOverride(pAC, pAC->IoBase, pAC->ActivePort, - (SK_MAC_ADDR*)dev->dev_addr, SK_ADDR_VIRTUAL_ADDRESS); - - - - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return 0; -} /* SkGeSetMacAddr */ - - -/***************************************************************************** - * - * SkGeSetRxMode - set receive mode - * - * Description: - * This function sets the receive mode of an adapter. The adapter - * supports promiscuous mode, allmulticast mode and a number of - * multicast addresses. If more multicast addresses the available - * are selected, a hash function in the hardware is used. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static void SkGeSetRxMode(struct SK_NET_DEVICE *dev) -{ - -DEV_NET *pNet; -SK_AC *pAC; - -struct dev_mc_list *pMcList; -int i; -int PortIdx; -unsigned long Flags; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeSetRxMode starts now... ")); - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - if (pAC->RlmtNets == 1) - PortIdx = pAC->ActivePort; - else - PortIdx = pNet->NetNr; - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - if (dev->flags & IFF_PROMISC) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("PROMISCUOUS mode\n")); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_LLC); - } else if (dev->flags & IFF_ALLMULTI) { - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("ALLMULTI mode\n")); - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_ALL_MC); - } else { - SkAddrPromiscuousChange(pAC, pAC->IoBase, PortIdx, - SK_PROM_MODE_NONE); - SkAddrMcClear(pAC, pAC->IoBase, PortIdx, 0); - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("Number of MC entries: %d ", dev->mc_count)); - - pMcList = dev->mc_list; - for (i=0; imc_count; i++, pMcList = pMcList->next) { - SkAddrMcAdd(pAC, pAC->IoBase, PortIdx, - (SK_MAC_ADDR*)pMcList->dmi_addr, 0); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_MCA, - ("%02x:%02x:%02x:%02x:%02x:%02x\n", - pMcList->dmi_addr[0], - pMcList->dmi_addr[1], - pMcList->dmi_addr[2], - pMcList->dmi_addr[3], - pMcList->dmi_addr[4], - pMcList->dmi_addr[5])); - } - SkAddrMcUpdate(pAC, pAC->IoBase, PortIdx); - } - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - return; -} /* SkGeSetRxMode */ - - -/***************************************************************************** - * - * SkGeChangeMtu - set the MTU to another value - * - * Description: - * This function sets is called whenever the MTU size is changed - * (ifconfig mtu xxx dev ethX). If the MTU is bigger than standard - * ethernet MTU size, long frame support is activated. - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeChangeMtu(struct SK_NET_DEVICE *dev, int NewMtu) -{ -DEV_NET *pNet; -struct net_device *pOtherDev; -SK_AC *pAC; -unsigned long Flags; -int i; -SK_EVPARA EvPara; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeChangeMtu starts now...\n")); - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - if ((NewMtu < 68) || (NewMtu > SK_JUMBO_MTU)) { - return -EINVAL; - } - - if(pAC->BoardLevel != SK_INIT_RUN) { - return -EINVAL; - } - -#ifdef SK_DIAG_SUPPORT - if (pAC->DiagModeActive == DIAG_ACTIVE) { - if (pAC->DiagFlowCtrl == SK_FALSE) { - return -1; /* still in use, deny any actions of MTU */ - } else { - pAC->DiagFlowCtrl = SK_FALSE; - } - } -#endif - - pOtherDev = pAC->dev[1 - pNet->NetNr]; - - if ( netif_running(pOtherDev) && (pOtherDev->mtu > 1500) - && (NewMtu <= 1500)) - return 0; - - pAC->RxBufSize = NewMtu + 32; - dev->mtu = NewMtu; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("New MTU: %d\n", NewMtu)); - - /* - ** Prevent any reconfiguration while changing the MTU - ** by disabling any interrupts - */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - - /* - ** Notify RLMT that any ports are to be stopped - */ - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - } else { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - } - - /* - ** After calling the SkEventDispatcher(), RLMT is aware about - ** the stopped ports -> configuration can take place! - */ - SkEventDispatcher(pAC, pAC->IoBase); - - for (i=0; iGIni.GIMacsFound; i++) { - spin_lock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); - netif_stop_queue(pAC->dev[i]); - - } - - /* - ** Depending on the desired MTU size change, a different number of - ** RX buffers need to be allocated - */ - if (NewMtu > 1500) { - /* - ** Use less rx buffers - */ - for (i=0; iGIni.GIMacsFound; i++) { - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - - (pAC->RxDescrPerRing / 4); - } else { - if (i == pAC->ActivePort) { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - - (pAC->RxDescrPerRing / 4); - } else { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - - (pAC->RxDescrPerRing / 10); - } - } - } - } else { - /* - ** Use the normal amount of rx buffers - */ - for (i=0; iGIni.GIMacsFound; i++) { - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - pAC->RxPort[i].RxFillLimit = 1; - } else { - if (i == pAC->ActivePort) { - pAC->RxPort[i].RxFillLimit = 1; - } else { - pAC->RxPort[i].RxFillLimit = pAC->RxDescrPerRing - - (pAC->RxDescrPerRing / 4); - } - } - } - } - - SkGeDeInit(pAC, pAC->IoBase); - - /* - ** enable/disable hardware support for long frames - */ - if (NewMtu > 1500) { -// pAC->JumboActivated = SK_TRUE; /* is never set back !!! */ - pAC->GIni.GIPortUsage = SK_JUMBO_LINK; - } else { - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - pAC->GIni.GIPortUsage = SK_MUL_LINK; - } else { - pAC->GIni.GIPortUsage = SK_RED_LINK; - } - } - - SkGeInit( pAC, pAC->IoBase, SK_INIT_IO); - SkI2cInit( pAC, pAC->IoBase, SK_INIT_IO); - SkEventInit(pAC, pAC->IoBase, SK_INIT_IO); - SkPnmiInit( pAC, pAC->IoBase, SK_INIT_IO); - SkAddrInit( pAC, pAC->IoBase, SK_INIT_IO); - SkRlmtInit( pAC, pAC->IoBase, SK_INIT_IO); - SkTimerInit(pAC, pAC->IoBase, SK_INIT_IO); - - /* - ** tschilling: - ** Speed and others are set back to default in level 1 init! - */ - GetConfiguration(pAC); - - SkGeInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkI2cInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkEventInit(pAC, pAC->IoBase, SK_INIT_RUN); - SkPnmiInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkAddrInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkRlmtInit( pAC, pAC->IoBase, SK_INIT_RUN); - SkTimerInit(pAC, pAC->IoBase, SK_INIT_RUN); - - /* - ** clear and reinit the rx rings here - */ - for (i=0; iGIni.GIMacsFound; i++) { - ReceiveIrq(pAC, &pAC->RxPort[i], SK_TRUE); - ClearRxRing(pAC, &pAC->RxPort[i]); - FillRxRing(pAC, &pAC->RxPort[i]); - - /* - ** Enable transmit descriptor polling - */ - SkGePollTxD(pAC, pAC->IoBase, i, SK_TRUE); - FillRxRing(pAC, &pAC->RxPort[i]); - }; - - SkGeYellowLED(pAC, pAC->IoBase, 1); - SkDimEnableModerationIfNeeded(pAC); - SkDimDisplayModerationSettings(pAC); - - netif_start_queue(pAC->dev[pNet->PortNr]); - for (i=pAC->GIni.GIMacsFound-1; i>=0; i--) { - spin_unlock(&pAC->TxPort[i][TX_PRIO_LOW].TxDesRingLock); - } - - /* - ** Enable Interrupts again - */ - SK_OUT32(pAC->IoBase, B0_IMSK, pAC->GIni.GIValIrqMask); - SK_OUT32(pAC->IoBase, B0_HWE_IMSK, IRQ_HWE_MASK); - - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - - /* - ** Notify RLMT about the changing and restarting one (or more) ports - */ - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - EvPara.Para32[0] = pAC->RlmtNets; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_SET_NETS, EvPara); - EvPara.Para32[0] = pNet->PortNr; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - - if (netif_running(pOtherDev)) { - DEV_NET *pOtherNet = netdev_priv(pOtherDev); - EvPara.Para32[0] = pOtherNet->PortNr; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - } - } else { - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_START, EvPara); - } - - SkEventDispatcher(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - /* - ** While testing this driver with latest kernel 2.5 (2.5.70), it - ** seems as if upper layers have a problem to handle a successful - ** return value of '0'. If such a zero is returned, the complete - ** system hangs for several minutes (!), which is in acceptable. - ** - ** Currently it is not clear, what the exact reason for this problem - ** is. The implemented workaround for 2.5 is to return the desired - ** new MTU size if all needed changes for the new MTU size where - ** performed. In kernels 2.2 and 2.4, a zero value is returned, - ** which indicates the successful change of the mtu-size. - */ - return NewMtu; - -} /* SkGeChangeMtu */ - - -/***************************************************************************** - * - * SkGeStats - return ethernet device statistics - * - * Description: - * This function return statistic data about the ethernet device - * to the operating system. - * - * Returns: - * pointer to the statistic structure. - */ -static struct net_device_stats *SkGeStats(struct SK_NET_DEVICE *dev) -{ -DEV_NET *pNet = netdev_priv(dev); -SK_AC *pAC = pNet->pAC; -SK_PNMI_STRUCT_DATA *pPnmiStruct; /* structure for all Pnmi-Data */ -SK_PNMI_STAT *pPnmiStat; /* pointer to virtual XMAC stat. data */ -SK_PNMI_CONF *pPnmiConf; /* pointer to virtual link config. */ -unsigned int Size; /* size of pnmi struct */ -unsigned long Flags; /* for spin lock */ - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeStats starts now...\n")); - pPnmiStruct = &pAC->PnmiStruct; - -#ifdef SK_DIAG_SUPPORT - if ((pAC->DiagModeActive == DIAG_NOTACTIVE) && - (pAC->BoardLevel == SK_INIT_RUN)) { -#endif - SK_MEMSET(pPnmiStruct, 0, sizeof(SK_PNMI_STRUCT_DATA)); - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - Size = SK_PNMI_STRUCT_SIZE; - SkPnmiGetStruct(pAC, pAC->IoBase, pPnmiStruct, &Size, pNet->NetNr); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); -#ifdef SK_DIAG_SUPPORT - } -#endif - - pPnmiStat = &pPnmiStruct->Stat[0]; - pPnmiConf = &pPnmiStruct->Conf[0]; - - pAC->stats.rx_packets = (SK_U32) pPnmiStruct->RxDeliveredCts & 0xFFFFFFFF; - pAC->stats.tx_packets = (SK_U32) pPnmiStat->StatTxOkCts & 0xFFFFFFFF; - pAC->stats.rx_bytes = (SK_U32) pPnmiStruct->RxOctetsDeliveredCts; - pAC->stats.tx_bytes = (SK_U32) pPnmiStat->StatTxOctetsOkCts; - - if (dev->mtu <= 1500) { - pAC->stats.rx_errors = (SK_U32) pPnmiStruct->InErrorsCts & 0xFFFFFFFF; - } else { - pAC->stats.rx_errors = (SK_U32) ((pPnmiStruct->InErrorsCts - - pPnmiStat->StatRxTooLongCts) & 0xFFFFFFFF); - } - - - if (pAC->GIni.GP[0].PhyType == SK_PHY_XMAC && pAC->HWRevision < 12) - pAC->stats.rx_errors = pAC->stats.rx_errors - pPnmiStat->StatRxShortsCts; - - pAC->stats.tx_errors = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; - pAC->stats.rx_dropped = (SK_U32) pPnmiStruct->RxNoBufCts & 0xFFFFFFFF; - pAC->stats.tx_dropped = (SK_U32) pPnmiStruct->TxNoBufCts & 0xFFFFFFFF; - pAC->stats.multicast = (SK_U32) pPnmiStat->StatRxMulticastOkCts & 0xFFFFFFFF; - pAC->stats.collisions = (SK_U32) pPnmiStat->StatTxSingleCollisionCts & 0xFFFFFFFF; - - /* detailed rx_errors: */ - pAC->stats.rx_length_errors = (SK_U32) pPnmiStat->StatRxRuntCts & 0xFFFFFFFF; - pAC->stats.rx_over_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; - pAC->stats.rx_crc_errors = (SK_U32) pPnmiStat->StatRxFcsCts & 0xFFFFFFFF; - pAC->stats.rx_frame_errors = (SK_U32) pPnmiStat->StatRxFramingCts & 0xFFFFFFFF; - pAC->stats.rx_fifo_errors = (SK_U32) pPnmiStat->StatRxFifoOverflowCts & 0xFFFFFFFF; - pAC->stats.rx_missed_errors = (SK_U32) pPnmiStat->StatRxMissedCts & 0xFFFFFFFF; - - /* detailed tx_errors */ - pAC->stats.tx_aborted_errors = (SK_U32) 0; - pAC->stats.tx_carrier_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; - pAC->stats.tx_fifo_errors = (SK_U32) pPnmiStat->StatTxFifoUnderrunCts & 0xFFFFFFFF; - pAC->stats.tx_heartbeat_errors = (SK_U32) pPnmiStat->StatTxCarrierCts & 0xFFFFFFFF; - pAC->stats.tx_window_errors = (SK_U32) 0; - - return(&pAC->stats); -} /* SkGeStats */ - -/* - * Basic MII register access - */ -static int SkGeMiiIoctl(struct net_device *dev, - struct mii_ioctl_data *data, int cmd) -{ - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - SK_IOC IoC = pAC->IoBase; - int Port = pNet->PortNr; - SK_GEPORT *pPrt = &pAC->GIni.GP[Port]; - unsigned long Flags; - int err = 0; - int reg = data->reg_num & 0x1f; - SK_U16 val = data->val_in; - - if (!netif_running(dev)) - return -ENODEV; /* Phy still in reset */ - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - switch(cmd) { - case SIOCGMIIPHY: - data->phy_id = pPrt->PhyAddr; - - /* fallthru */ - case SIOCGMIIREG: - if (pAC->GIni.GIGenesis) - SkXmPhyRead(pAC, IoC, Port, reg, &val); - else - SkGmPhyRead(pAC, IoC, Port, reg, &val); - - data->val_out = val; - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - err = -EPERM; - - else if (pAC->GIni.GIGenesis) - SkXmPhyWrite(pAC, IoC, Port, reg, val); - else - SkGmPhyWrite(pAC, IoC, Port, reg, val); - break; - default: - err = -EOPNOTSUPP; - } - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - return err; -} - - -/***************************************************************************** - * - * SkGeIoctl - IO-control function - * - * Description: - * This function is called if an ioctl is issued on the device. - * There are three subfunction for reading, writing and test-writing - * the private MIB data structure (useful for SysKonnect-internal tools). - * - * Returns: - * 0, if everything is ok - * !=0, on error - */ -static int SkGeIoctl(struct SK_NET_DEVICE *dev, struct ifreq *rq, int cmd) -{ -DEV_NET *pNet; -SK_AC *pAC; -void *pMemBuf; -struct pci_dev *pdev = NULL; -SK_GE_IOCTL Ioctl; -unsigned int Err = 0; -int Size = 0; -int Ret = 0; -unsigned int Length = 0; -int HeaderLength = sizeof(SK_U32) + sizeof(SK_U32); - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeIoctl starts now...\n")); - - pNet = netdev_priv(dev); - pAC = pNet->pAC; - - if (cmd == SIOCGMIIPHY || cmd == SIOCSMIIREG || cmd == SIOCGMIIREG) - return SkGeMiiIoctl(dev, if_mii(rq), cmd); - - if(copy_from_user(&Ioctl, rq->ifr_data, sizeof(SK_GE_IOCTL))) { - return -EFAULT; - } - - switch(cmd) { - case SK_IOCTL_SETMIB: - case SK_IOCTL_PRESETMIB: - if (!capable(CAP_NET_ADMIN)) return -EPERM; - case SK_IOCTL_GETMIB: - if(copy_from_user(&pAC->PnmiStruct, Ioctl.pData, - Ioctl.LenPnmiStruct)? - Ioctl.Len : sizeof(pAC->PnmiStruct))) { - return -EFAULT; - } - Size = SkGeIocMib(pNet, Ioctl.Len, cmd); - if(copy_to_user(Ioctl.pData, &pAC->PnmiStruct, - Ioctl.Lenifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { - return -EFAULT; - } - break; - case SK_IOCTL_GEN: - if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) { - Length = Ioctl.Len; - } else { - Length = sizeof(pAC->PnmiStruct) + HeaderLength; - } - if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) { - return -ENOMEM; - } - if(copy_from_user(pMemBuf, Ioctl.pData, Length)) { - Err = -EFAULT; - goto fault_gen; - } - if ((Ret = SkPnmiGenIoctl(pAC, pAC->IoBase, pMemBuf, &Length, 0)) < 0) { - Err = -EFAULT; - goto fault_gen; - } - if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { - Err = -EFAULT; - goto fault_gen; - } - Ioctl.Len = Length; - if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { - Err = -EFAULT; - goto fault_gen; - } -fault_gen: - kfree(pMemBuf); /* cleanup everything */ - break; -#ifdef SK_DIAG_SUPPORT - case SK_IOCTL_DIAG: - if (!capable(CAP_NET_ADMIN)) return -EPERM; - if (Ioctl.Len < (sizeof(pAC->PnmiStruct) + HeaderLength)) { - Length = Ioctl.Len; - } else { - Length = sizeof(pAC->PnmiStruct) + HeaderLength; - } - if (NULL == (pMemBuf = kmalloc(Length, GFP_KERNEL))) { - return -ENOMEM; - } - if(copy_from_user(pMemBuf, Ioctl.pData, Length)) { - Err = -EFAULT; - goto fault_diag; - } - pdev = pAC->PciDev; - Length = 3 * sizeof(SK_U32); /* Error, Bus and Device */ - /* - ** While coding this new IOCTL interface, only a few lines of code - ** are to to be added. Therefore no dedicated function has been - ** added. If more functionality is added, a separate function - ** should be used... - */ - * ((SK_U32 *)pMemBuf) = 0; - * ((SK_U32 *)pMemBuf + 1) = pdev->bus->number; - * ((SK_U32 *)pMemBuf + 2) = ParseDeviceNbrFromSlotName(pci_name(pdev)); - if(copy_to_user(Ioctl.pData, pMemBuf, Length) ) { - Err = -EFAULT; - goto fault_diag; - } - Ioctl.Len = Length; - if(copy_to_user(rq->ifr_data, &Ioctl, sizeof(SK_GE_IOCTL))) { - Err = -EFAULT; - goto fault_diag; - } -fault_diag: - kfree(pMemBuf); /* cleanup everything */ - break; -#endif - default: - Err = -EOPNOTSUPP; - } - - return(Err); - -} /* SkGeIoctl */ - - -/***************************************************************************** - * - * SkGeIocMib - handle a GetMib, SetMib- or PresetMib-ioctl message - * - * Description: - * This function reads/writes the MIB data using PNMI (Private Network - * Management Interface). - * The destination for the data must be provided with the - * ioctl call and is given to the driver in the form of - * a user space address. - * Copying from the user-provided data area into kernel messages - * and back is done by copy_from_user and copy_to_user calls in - * SkGeIoctl. - * - * Returns: - * returned size from PNMI call - */ -static int SkGeIocMib( -DEV_NET *pNet, /* pointer to the adapter context */ -unsigned int Size, /* length of ioctl data */ -int mode) /* flag for set/preset */ -{ -unsigned long Flags; /* for spin lock */ -SK_AC *pAC; - - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("SkGeIocMib starts now...\n")); - pAC = pNet->pAC; - /* access MIB */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - switch(mode) { - case SK_IOCTL_GETMIB: - SkPnmiGetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - case SK_IOCTL_PRESETMIB: - SkPnmiPreSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - case SK_IOCTL_SETMIB: - SkPnmiSetStruct(pAC, pAC->IoBase, &pAC->PnmiStruct, &Size, - pNet->NetNr); - break; - default: - break; - } - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_ENTRY, - ("MIB data access succeeded\n")); - return (Size); -} /* SkGeIocMib */ - - -/***************************************************************************** - * - * GetConfiguration - read configuration information - * - * Description: - * This function reads per-adapter configuration information from - * the options provided on the command line. - * - * Returns: - * none - */ -static void GetConfiguration( -SK_AC *pAC) /* pointer to the adapter context structure */ -{ -SK_I32 Port; /* preferred port */ -SK_BOOL AutoSet; -SK_BOOL DupSet; -int LinkSpeed = SK_LSPEED_AUTO; /* Link speed */ -int AutoNeg = 1; /* autoneg off (0) or on (1) */ -int DuplexCap = 0; /* 0=both,1=full,2=half */ -int FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; /* FlowControl */ -int MSMode = SK_MS_MODE_AUTO; /* master/slave mode */ - -SK_BOOL IsConTypeDefined = SK_TRUE; -SK_BOOL IsLinkSpeedDefined = SK_TRUE; -SK_BOOL IsFlowCtrlDefined = SK_TRUE; -SK_BOOL IsRoleDefined = SK_TRUE; -SK_BOOL IsModeDefined = SK_TRUE; -/* - * The two parameters AutoNeg. and DuplexCap. map to one configuration - * parameter. The mapping is described by this table: - * DuplexCap -> | both | full | half | - * AutoNeg | | | | - * ----------------------------------------------------------------- - * Off | illegal | Full | Half | - * ----------------------------------------------------------------- - * On | AutoBoth | AutoFull | AutoHalf | - * ----------------------------------------------------------------- - * Sense | AutoSense | AutoSense | AutoSense | - */ -int Capabilities[3][3] = - { { -1, SK_LMODE_FULL , SK_LMODE_HALF }, - {SK_LMODE_AUTOBOTH , SK_LMODE_AUTOFULL , SK_LMODE_AUTOHALF }, - {SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE, SK_LMODE_AUTOSENSE} }; - -#define DC_BOTH 0 -#define DC_FULL 1 -#define DC_HALF 2 -#define AN_OFF 0 -#define AN_ON 1 -#define AN_SENS 2 -#define M_CurrPort pAC->GIni.GP[Port] - - - /* - ** Set the default values first for both ports! - */ - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO; - } - - /* - ** Check merged parameter ConType. If it has not been used, - ** verify any other parameter (e.g. AutoNeg) and use default values. - ** - ** Stating both ConType and other lowlevel link parameters is also - ** possible. If this is the case, the passed ConType-parameter is - ** overwritten by the lowlevel link parameter. - ** - ** The following settings are used for a merged ConType-parameter: - ** - ** ConType DupCap AutoNeg FlowCtrl Role Speed - ** ------- ------ ------- -------- ---------- ----- - ** Auto Both On SymOrRem Auto Auto - ** 100FD Full Off None 100 - ** 100HD Half Off None 100 - ** 10FD Full Off None 10 - ** 10HD Half Off None 10 - ** - ** This ConType parameter is used for all ports of the adapter! - */ - if ( (ConType != NULL) && - (pAC->Index < SK_MAX_CARD_PARAM) && - (ConType[pAC->Index] != NULL) ) { - - /* Check chipset family */ - if ((!pAC->ChipsetType) && - (strcmp(ConType[pAC->Index],"Auto")!=0) && - (strcmp(ConType[pAC->Index],"")!=0)) { - /* Set the speed parameter back */ - printk("sk98lin: Illegal value \"%s\" " - "for ConType." - " Using Auto.\n", - ConType[pAC->Index]); - - sprintf(ConType[pAC->Index], "Auto"); - } - - if (strcmp(ConType[pAC->Index],"")==0) { - IsConTypeDefined = SK_FALSE; /* No ConType defined */ - } else if (strcmp(ConType[pAC->Index],"Auto")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_ON][DC_BOTH]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_SYM_OR_REM; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_AUTO; - } - } else if (strcmp(ConType[pAC->Index],"100FD")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS; - } - } else if (strcmp(ConType[pAC->Index],"100HD")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_100MBPS; - } - } else if (strcmp(ConType[pAC->Index],"10FD")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_FULL]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS; - } - } else if (strcmp(ConType[pAC->Index],"10HD")==0) { - for (Port = 0; Port < SK_MAX_MACS; Port++) { - M_CurrPort.PLinkModeConf = Capabilities[AN_OFF][DC_HALF]; - M_CurrPort.PFlowCtrlMode = SK_FLOW_MODE_NONE; - M_CurrPort.PMSMode = SK_MS_MODE_AUTO; - M_CurrPort.PLinkSpeed = SK_LSPEED_10MBPS; - } - } else { - printk("sk98lin: Illegal value \"%s\" for ConType\n", - ConType[pAC->Index]); - IsConTypeDefined = SK_FALSE; /* Wrong ConType defined */ - } - } else { - IsConTypeDefined = SK_FALSE; /* No ConType defined */ - } - - /* - ** Parse any parameter settings for port A: - ** a) any LinkSpeed stated? - */ - if (Speed_A != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(Speed_A[pAC->Index],"")==0) { - IsLinkSpeedDefined = SK_FALSE; - } else if (strcmp(Speed_A[pAC->Index],"Auto")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } else if (strcmp(Speed_A[pAC->Index],"10")==0) { - LinkSpeed = SK_LSPEED_10MBPS; - } else if (strcmp(Speed_A[pAC->Index],"100")==0) { - LinkSpeed = SK_LSPEED_100MBPS; - } else if (strcmp(Speed_A[pAC->Index],"1000")==0) { - LinkSpeed = SK_LSPEED_1000MBPS; - } else { - printk("sk98lin: Illegal value \"%s\" for Speed_A\n", - Speed_A[pAC->Index]); - IsLinkSpeedDefined = SK_FALSE; - } - } else { - IsLinkSpeedDefined = SK_FALSE; - } - - /* - ** Check speed parameter: - ** Only copper type adapter and GE V2 cards - */ - if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) && - ((LinkSpeed != SK_LSPEED_AUTO) && - (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("sk98lin: Illegal value for Speed_A. " - "Not a copper card or GE V2 card\n Using " - "speed 1000\n"); - LinkSpeed = SK_LSPEED_1000MBPS; - } - - /* - ** Decide whether to set new config value if somethig valid has - ** been received. - */ - if (IsLinkSpeedDefined) { - pAC->GIni.GP[0].PLinkSpeed = LinkSpeed; - } - - /* - ** b) Any Autonegotiation and DuplexCapabilities set? - ** Please note that both belong together... - */ - AutoNeg = AN_ON; /* tschilling: Default: Autonegotiation on! */ - AutoSet = SK_FALSE; - if (AutoNeg_A != NULL && pAC->IndexIndex] != NULL) { - AutoSet = SK_TRUE; - if (strcmp(AutoNeg_A[pAC->Index],"")==0) { - AutoSet = SK_FALSE; - } else if (strcmp(AutoNeg_A[pAC->Index],"On")==0) { - AutoNeg = AN_ON; - } else if (strcmp(AutoNeg_A[pAC->Index],"Off")==0) { - AutoNeg = AN_OFF; - } else if (strcmp(AutoNeg_A[pAC->Index],"Sense")==0) { - AutoNeg = AN_SENS; - } else { - printk("sk98lin: Illegal value \"%s\" for AutoNeg_A\n", - AutoNeg_A[pAC->Index]); - } - } - - DuplexCap = DC_BOTH; - DupSet = SK_FALSE; - if (DupCap_A != NULL && pAC->IndexIndex] != NULL) { - DupSet = SK_TRUE; - if (strcmp(DupCap_A[pAC->Index],"")==0) { - DupSet = SK_FALSE; - } else if (strcmp(DupCap_A[pAC->Index],"Both")==0) { - DuplexCap = DC_BOTH; - } else if (strcmp(DupCap_A[pAC->Index],"Full")==0) { - DuplexCap = DC_FULL; - } else if (strcmp(DupCap_A[pAC->Index],"Half")==0) { - DuplexCap = DC_HALF; - } else { - printk("sk98lin: Illegal value \"%s\" for DupCap_A\n", - DupCap_A[pAC->Index]); - } - } - - /* - ** Check for illegal combinations - */ - if ((LinkSpeed == SK_LSPEED_1000MBPS) && - ((DuplexCap == SK_LMODE_STAT_AUTOHALF) || - (DuplexCap == SK_LMODE_STAT_HALF)) && - (pAC->ChipsetType)) { - printk("sk98lin: Half Duplex not possible with Gigabit speed!\n" - " Using Full Duplex.\n"); - DuplexCap = DC_FULL; - } - - if ( AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("sk98lin, Port A: DuplexCapabilities" - " ignored using Sense mode\n"); - } - - if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("sk98lin: Port A: Illegal combination" - " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n"); - DuplexCap = DC_FULL; - } - - if (AutoSet && AutoNeg==AN_OFF && !DupSet) { - DuplexCap = DC_FULL; - } - - if (!AutoSet && DupSet) { - printk("sk98lin: Port A: Duplex setting not" - " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n"); - AutoNeg = AN_ON; - } - - /* - ** set the desired mode - */ - if (AutoSet || DupSet) { - pAC->GIni.GP[0].PLinkModeConf = Capabilities[AutoNeg][DuplexCap]; - } - - /* - ** c) Any Flowcontrol-parameter set? - */ - if (FlowCtrl_A != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(FlowCtrl_A[pAC->Index],"") == 0) { - IsFlowCtrlDefined = SK_FALSE; - } else if (strcmp(FlowCtrl_A[pAC->Index],"SymOrRem") == 0) { - FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; - } else if (strcmp(FlowCtrl_A[pAC->Index],"Sym")==0) { - FlowCtrl = SK_FLOW_MODE_SYMMETRIC; - } else if (strcmp(FlowCtrl_A[pAC->Index],"LocSend")==0) { - FlowCtrl = SK_FLOW_MODE_LOC_SEND; - } else if (strcmp(FlowCtrl_A[pAC->Index],"None")==0) { - FlowCtrl = SK_FLOW_MODE_NONE; - } else { - printk("sk98lin: Illegal value \"%s\" for FlowCtrl_A\n", - FlowCtrl_A[pAC->Index]); - IsFlowCtrlDefined = SK_FALSE; - } - } else { - IsFlowCtrlDefined = SK_FALSE; - } - - if (IsFlowCtrlDefined) { - if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) { - printk("sk98lin: Port A: FlowControl" - " impossible without AutoNegotiation," - " disabled\n"); - FlowCtrl = SK_FLOW_MODE_NONE; - } - pAC->GIni.GP[0].PFlowCtrlMode = FlowCtrl; - } - - /* - ** d) What is with the RoleParameter? - */ - if (Role_A != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(Role_A[pAC->Index],"")==0) { - IsRoleDefined = SK_FALSE; - } else if (strcmp(Role_A[pAC->Index],"Auto")==0) { - MSMode = SK_MS_MODE_AUTO; - } else if (strcmp(Role_A[pAC->Index],"Master")==0) { - MSMode = SK_MS_MODE_MASTER; - } else if (strcmp(Role_A[pAC->Index],"Slave")==0) { - MSMode = SK_MS_MODE_SLAVE; - } else { - printk("sk98lin: Illegal value \"%s\" for Role_A\n", - Role_A[pAC->Index]); - IsRoleDefined = SK_FALSE; - } - } else { - IsRoleDefined = SK_FALSE; - } - - if (IsRoleDefined == SK_TRUE) { - pAC->GIni.GP[0].PMSMode = MSMode; - } - - - - /* - ** Parse any parameter settings for port B: - ** a) any LinkSpeed stated? - */ - IsConTypeDefined = SK_TRUE; - IsLinkSpeedDefined = SK_TRUE; - IsFlowCtrlDefined = SK_TRUE; - IsModeDefined = SK_TRUE; - - if (Speed_B != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(Speed_B[pAC->Index],"")==0) { - IsLinkSpeedDefined = SK_FALSE; - } else if (strcmp(Speed_B[pAC->Index],"Auto")==0) { - LinkSpeed = SK_LSPEED_AUTO; - } else if (strcmp(Speed_B[pAC->Index],"10")==0) { - LinkSpeed = SK_LSPEED_10MBPS; - } else if (strcmp(Speed_B[pAC->Index],"100")==0) { - LinkSpeed = SK_LSPEED_100MBPS; - } else if (strcmp(Speed_B[pAC->Index],"1000")==0) { - LinkSpeed = SK_LSPEED_1000MBPS; - } else { - printk("sk98lin: Illegal value \"%s\" for Speed_B\n", - Speed_B[pAC->Index]); - IsLinkSpeedDefined = SK_FALSE; - } - } else { - IsLinkSpeedDefined = SK_FALSE; - } - - /* - ** Check speed parameter: - ** Only copper type adapter and GE V2 cards - */ - if (((!pAC->ChipsetType) || (pAC->GIni.GICopperType != SK_TRUE)) && - ((LinkSpeed != SK_LSPEED_AUTO) && - (LinkSpeed != SK_LSPEED_1000MBPS))) { - printk("sk98lin: Illegal value for Speed_B. " - "Not a copper card or GE V2 card\n Using " - "speed 1000\n"); - LinkSpeed = SK_LSPEED_1000MBPS; - } - - /* - ** Decide whether to set new config value if somethig valid has - ** been received. - */ - if (IsLinkSpeedDefined) { - pAC->GIni.GP[1].PLinkSpeed = LinkSpeed; - } - - /* - ** b) Any Autonegotiation and DuplexCapabilities set? - ** Please note that both belong together... - */ - AutoNeg = AN_SENS; /* default: do auto Sense */ - AutoSet = SK_FALSE; - if (AutoNeg_B != NULL && pAC->IndexIndex] != NULL) { - AutoSet = SK_TRUE; - if (strcmp(AutoNeg_B[pAC->Index],"")==0) { - AutoSet = SK_FALSE; - } else if (strcmp(AutoNeg_B[pAC->Index],"On")==0) { - AutoNeg = AN_ON; - } else if (strcmp(AutoNeg_B[pAC->Index],"Off")==0) { - AutoNeg = AN_OFF; - } else if (strcmp(AutoNeg_B[pAC->Index],"Sense")==0) { - AutoNeg = AN_SENS; - } else { - printk("sk98lin: Illegal value \"%s\" for AutoNeg_B\n", - AutoNeg_B[pAC->Index]); - } - } - - DuplexCap = DC_BOTH; - DupSet = SK_FALSE; - if (DupCap_B != NULL && pAC->IndexIndex] != NULL) { - DupSet = SK_TRUE; - if (strcmp(DupCap_B[pAC->Index],"")==0) { - DupSet = SK_FALSE; - } else if (strcmp(DupCap_B[pAC->Index],"Both")==0) { - DuplexCap = DC_BOTH; - } else if (strcmp(DupCap_B[pAC->Index],"Full")==0) { - DuplexCap = DC_FULL; - } else if (strcmp(DupCap_B[pAC->Index],"Half")==0) { - DuplexCap = DC_HALF; - } else { - printk("sk98lin: Illegal value \"%s\" for DupCap_B\n", - DupCap_B[pAC->Index]); - } - } - - - /* - ** Check for illegal combinations - */ - if ((LinkSpeed == SK_LSPEED_1000MBPS) && - ((DuplexCap == SK_LMODE_STAT_AUTOHALF) || - (DuplexCap == SK_LMODE_STAT_HALF)) && - (pAC->ChipsetType)) { - printk("sk98lin: Half Duplex not possible with Gigabit speed!\n" - " Using Full Duplex.\n"); - DuplexCap = DC_FULL; - } - - if (AutoSet && AutoNeg==AN_SENS && DupSet) { - printk("sk98lin, Port B: DuplexCapabilities" - " ignored using Sense mode\n"); - } - - if (AutoSet && AutoNeg==AN_OFF && DupSet && DuplexCap==DC_BOTH){ - printk("sk98lin: Port B: Illegal combination" - " of values AutoNeg. and DuplexCap.\n Using " - "Full Duplex\n"); - DuplexCap = DC_FULL; - } - - if (AutoSet && AutoNeg==AN_OFF && !DupSet) { - DuplexCap = DC_FULL; - } - - if (!AutoSet && DupSet) { - printk("sk98lin: Port B: Duplex setting not" - " possible in\n default AutoNegotiation mode" - " (Sense).\n Using AutoNegotiation On\n"); - AutoNeg = AN_ON; - } - - /* - ** set the desired mode - */ - if (AutoSet || DupSet) { - pAC->GIni.GP[1].PLinkModeConf = Capabilities[AutoNeg][DuplexCap]; - } - - /* - ** c) Any FlowCtrl parameter set? - */ - if (FlowCtrl_B != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(FlowCtrl_B[pAC->Index],"") == 0) { - IsFlowCtrlDefined = SK_FALSE; - } else if (strcmp(FlowCtrl_B[pAC->Index],"SymOrRem") == 0) { - FlowCtrl = SK_FLOW_MODE_SYM_OR_REM; - } else if (strcmp(FlowCtrl_B[pAC->Index],"Sym")==0) { - FlowCtrl = SK_FLOW_MODE_SYMMETRIC; - } else if (strcmp(FlowCtrl_B[pAC->Index],"LocSend")==0) { - FlowCtrl = SK_FLOW_MODE_LOC_SEND; - } else if (strcmp(FlowCtrl_B[pAC->Index],"None")==0) { - FlowCtrl = SK_FLOW_MODE_NONE; - } else { - printk("sk98lin: Illegal value \"%s\" for FlowCtrl_B\n", - FlowCtrl_B[pAC->Index]); - IsFlowCtrlDefined = SK_FALSE; - } - } else { - IsFlowCtrlDefined = SK_FALSE; - } - - if (IsFlowCtrlDefined) { - if ((AutoNeg == AN_OFF) && (FlowCtrl != SK_FLOW_MODE_NONE)) { - printk("sk98lin: Port B: FlowControl" - " impossible without AutoNegotiation," - " disabled\n"); - FlowCtrl = SK_FLOW_MODE_NONE; - } - pAC->GIni.GP[1].PFlowCtrlMode = FlowCtrl; - } - - /* - ** d) What is the RoleParameter? - */ - if (Role_B != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(Role_B[pAC->Index],"")==0) { - IsRoleDefined = SK_FALSE; - } else if (strcmp(Role_B[pAC->Index],"Auto")==0) { - MSMode = SK_MS_MODE_AUTO; - } else if (strcmp(Role_B[pAC->Index],"Master")==0) { - MSMode = SK_MS_MODE_MASTER; - } else if (strcmp(Role_B[pAC->Index],"Slave")==0) { - MSMode = SK_MS_MODE_SLAVE; - } else { - printk("sk98lin: Illegal value \"%s\" for Role_B\n", - Role_B[pAC->Index]); - IsRoleDefined = SK_FALSE; - } - } else { - IsRoleDefined = SK_FALSE; - } - - if (IsRoleDefined) { - pAC->GIni.GP[1].PMSMode = MSMode; - } - - /* - ** Evaluate settings for both ports - */ - pAC->ActivePort = 0; - if (PrefPort != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(PrefPort[pAC->Index],"") == 0) { /* Auto */ - pAC->ActivePort = 0; - pAC->Rlmt.Net[0].Preference = -1; /* auto */ - pAC->Rlmt.Net[0].PrefPort = 0; - } else if (strcmp(PrefPort[pAC->Index],"A") == 0) { - /* - ** do not set ActivePort here, thus a port - ** switch is issued after net up. - */ - Port = 0; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; - } else if (strcmp(PrefPort[pAC->Index],"B") == 0) { - /* - ** do not set ActivePort here, thus a port - ** switch is issued after net up. - */ - if (pAC->GIni.GIMacsFound == 1) { - printk("sk98lin: Illegal value \"B\" for PrefPort.\n" - " Port B not available on single port adapters.\n"); - - pAC->ActivePort = 0; - pAC->Rlmt.Net[0].Preference = -1; /* auto */ - pAC->Rlmt.Net[0].PrefPort = 0; - } else { - Port = 1; - pAC->Rlmt.Net[0].Preference = Port; - pAC->Rlmt.Net[0].PrefPort = Port; - } - } else { - printk("sk98lin: Illegal value \"%s\" for PrefPort\n", - PrefPort[pAC->Index]); - } - } - - pAC->RlmtNets = 1; - - if (RlmtMode != NULL && pAC->IndexIndex] != NULL) { - if (strcmp(RlmtMode[pAC->Index], "") == 0) { - pAC->RlmtMode = 0; - } else if (strcmp(RlmtMode[pAC->Index], "CheckLinkState") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK; - } else if (strcmp(RlmtMode[pAC->Index], "CheckLocalPort") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK | - SK_RLMT_CHECK_LOC_LINK; - } else if (strcmp(RlmtMode[pAC->Index], "CheckSeg") == 0) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK | - SK_RLMT_CHECK_LOC_LINK | - SK_RLMT_CHECK_SEG; - } else if ((strcmp(RlmtMode[pAC->Index], "DualNet") == 0) && - (pAC->GIni.GIMacsFound == 2)) { - pAC->RlmtMode = SK_RLMT_CHECK_LINK; - pAC->RlmtNets = 2; - } else { - printk("sk98lin: Illegal value \"%s\" for" - " RlmtMode, using default\n", - RlmtMode[pAC->Index]); - pAC->RlmtMode = 0; - } - } else { - pAC->RlmtMode = 0; - } - - /* - ** Check the interrupt moderation parameters - */ - if (Moderation[pAC->Index] != NULL) { - if (strcmp(Moderation[pAC->Index], "") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } else if (strcmp(Moderation[pAC->Index], "Static") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_STATIC; - } else if (strcmp(Moderation[pAC->Index], "Dynamic") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_DYNAMIC; - } else if (strcmp(Moderation[pAC->Index], "None") == 0) { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } else { - printk("sk98lin: Illegal value \"%s\" for Moderation.\n" - " Disable interrupt moderation.\n", - Moderation[pAC->Index]); - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } - } else { - pAC->DynIrqModInfo.IntModTypeSelect = C_INT_MOD_NONE; - } - - if (Stats[pAC->Index] != NULL) { - if (strcmp(Stats[pAC->Index], "Yes") == 0) { - pAC->DynIrqModInfo.DisplayStats = SK_TRUE; - } else { - pAC->DynIrqModInfo.DisplayStats = SK_FALSE; - } - } else { - pAC->DynIrqModInfo.DisplayStats = SK_FALSE; - } - - if (ModerationMask[pAC->Index] != NULL) { - if (strcmp(ModerationMask[pAC->Index], "Rx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "Tx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "Sp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_ONLY; - } else if (strcmp(ModerationMask[pAC->Index], "RxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX; - } else if (strcmp(ModerationMask[pAC->Index], "SpRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_RX; - } else if (strcmp(ModerationMask[pAC->Index], "RxTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } else if (strcmp(ModerationMask[pAC->Index], "TxRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } else if (strcmp(ModerationMask[pAC->Index], "TxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX; - } else if (strcmp(ModerationMask[pAC->Index], "SpTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_SP_TX; - } else if (strcmp(ModerationMask[pAC->Index], "RxTxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "RxSpTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "TxRxSp") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "TxSpRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "SpTxRx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else if (strcmp(ModerationMask[pAC->Index], "SpRxTx") == 0) { - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_TX_SP; - } else { /* some rubbish */ - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_RX_ONLY; - } - } else { /* operator has stated nothing */ - pAC->DynIrqModInfo.MaskIrqModeration = IRQ_MASK_TX_RX; - } - - if (AutoSizing[pAC->Index] != NULL) { - if (strcmp(AutoSizing[pAC->Index], "On") == 0) { - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } else { - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } - } else { /* operator has stated nothing */ - pAC->DynIrqModInfo.AutoSizing = SK_FALSE; - } - - if (IntsPerSec[pAC->Index] != 0) { - if ((IntsPerSec[pAC->Index]< C_INT_MOD_IPS_LOWER_RANGE) || - (IntsPerSec[pAC->Index] > C_INT_MOD_IPS_UPPER_RANGE)) { - printk("sk98lin: Illegal value \"%d\" for IntsPerSec. (Range: %d - %d)\n" - " Using default value of %i.\n", - IntsPerSec[pAC->Index], - C_INT_MOD_IPS_LOWER_RANGE, - C_INT_MOD_IPS_UPPER_RANGE, - C_INTS_PER_SEC_DEFAULT); - pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; - } else { - pAC->DynIrqModInfo.MaxModIntsPerSec = IntsPerSec[pAC->Index]; - } - } else { - pAC->DynIrqModInfo.MaxModIntsPerSec = C_INTS_PER_SEC_DEFAULT; - } - - /* - ** Evaluate upper and lower moderation threshold - */ - pAC->DynIrqModInfo.MaxModIntsPerSecUpperLimit = - pAC->DynIrqModInfo.MaxModIntsPerSec + - (pAC->DynIrqModInfo.MaxModIntsPerSec / 2); - - pAC->DynIrqModInfo.MaxModIntsPerSecLowerLimit = - pAC->DynIrqModInfo.MaxModIntsPerSec - - (pAC->DynIrqModInfo.MaxModIntsPerSec / 2); - - pAC->DynIrqModInfo.PrevTimeVal = jiffies; /* initial value */ - - -} /* GetConfiguration */ - - -/***************************************************************************** - * - * ProductStr - return a adapter identification string from vpd - * - * Description: - * This function reads the product name string from the vpd area - * and puts it the field pAC->DeviceString. - * - * Returns: N/A - */ -static inline int ProductStr( - SK_AC *pAC, /* pointer to adapter context */ - char *DeviceStr, /* result string */ - int StrLen /* length of the string */ -) -{ -char Keyword[] = VPD_NAME; /* vpd productname identifier */ -int ReturnCode; /* return code from vpd_read */ -unsigned long Flags; - - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - ReturnCode = VpdRead(pAC, pAC->IoBase, Keyword, DeviceStr, &StrLen); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - - return ReturnCode; -} /* ProductStr */ - -/***************************************************************************** - * - * StartDrvCleanupTimer - Start timer to check for descriptors which - * might be placed in descriptor ring, but - * havent been handled up to now - * - * Description: - * This function requests a HW-timer fo the Yukon card. The actions to - * perform when this timer expires, are located in the SkDrvEvent(). - * - * Returns: N/A - */ -static void -StartDrvCleanupTimer(SK_AC *pAC) { - SK_EVPARA EventParam; /* Event struct for timer event */ - - SK_MEMSET((char *) &EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = SK_DRV_RX_CLEANUP_TIMER; - SkTimerStart(pAC, pAC->IoBase, &pAC->DrvCleanupTimer, - SK_DRV_RX_CLEANUP_TIMER_LENGTH, - SKGE_DRV, SK_DRV_TIMER, EventParam); -} - -/***************************************************************************** - * - * StopDrvCleanupTimer - Stop timer to check for descriptors - * - * Description: - * This function requests a HW-timer fo the Yukon card. The actions to - * perform when this timer expires, are located in the SkDrvEvent(). - * - * Returns: N/A - */ -static void -StopDrvCleanupTimer(SK_AC *pAC) { - SkTimerStop(pAC, pAC->IoBase, &pAC->DrvCleanupTimer); - SK_MEMSET((char *) &pAC->DrvCleanupTimer, 0, sizeof(SK_TIMER)); -} - -/****************************************************************************/ -/* functions for common modules *********************************************/ -/****************************************************************************/ - - -/***************************************************************************** - * - * SkDrvAllocRlmtMbuf - allocate an RLMT mbuf - * - * Description: - * This routine returns an RLMT mbuf or NULL. The RLMT Mbuf structure - * is embedded into a socket buff data area. - * - * Context: - * runtime - * - * Returns: - * NULL or pointer to Mbuf. - */ -SK_MBUF *SkDrvAllocRlmtMbuf( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* the IO-context */ -unsigned BufferSize) /* size of the requested buffer */ -{ -SK_MBUF *pRlmtMbuf; /* pointer to a new rlmt-mbuf structure */ -struct sk_buff *pMsgBlock; /* pointer to a new message block */ - - pMsgBlock = alloc_skb(BufferSize + sizeof(SK_MBUF), GFP_ATOMIC); - if (pMsgBlock == NULL) { - return (NULL); - } - pRlmtMbuf = (SK_MBUF*) pMsgBlock->data; - skb_reserve(pMsgBlock, sizeof(SK_MBUF)); - pRlmtMbuf->pNext = NULL; - pRlmtMbuf->pOs = pMsgBlock; - pRlmtMbuf->pData = pMsgBlock->data; /* Data buffer. */ - pRlmtMbuf->Size = BufferSize; /* Data buffer size. */ - pRlmtMbuf->Length = 0; /* Length of packet (<= Size). */ - return (pRlmtMbuf); - -} /* SkDrvAllocRlmtMbuf */ - - -/***************************************************************************** - * - * SkDrvFreeRlmtMbuf - free an RLMT mbuf - * - * Description: - * This routine frees one or more RLMT mbuf(s). - * - * Context: - * runtime - * - * Returns: - * Nothing - */ -void SkDrvFreeRlmtMbuf( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* the IO-context */ -SK_MBUF *pMbuf) /* size of the requested buffer */ -{ -SK_MBUF *pFreeMbuf; -SK_MBUF *pNextMbuf; - - pFreeMbuf = pMbuf; - do { - pNextMbuf = pFreeMbuf->pNext; - DEV_KFREE_SKB_ANY(pFreeMbuf->pOs); - pFreeMbuf = pNextMbuf; - } while ( pFreeMbuf != NULL ); -} /* SkDrvFreeRlmtMbuf */ - - -/***************************************************************************** - * - * SkOsGetTime - provide a time value - * - * Description: - * This routine provides a time value. The unit is 1/HZ (defined by Linux). - * It is not used for absolute time, but only for time differences. - * - * - * Returns: - * Time value - */ -SK_U64 SkOsGetTime(SK_AC *pAC) -{ - SK_U64 PrivateJiffies; - SkOsGetTimeCurrent(pAC, &PrivateJiffies); - return PrivateJiffies; -} /* SkOsGetTime */ - - -/***************************************************************************** - * - * SkPciReadCfgDWord - read a 32 bit value from pci config space - * - * Description: - * This routine reads a 32 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgDWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U32 *pVal) /* pointer to store the read value */ -{ - pci_read_config_dword(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgDWord */ - - -/***************************************************************************** - * - * SkPciReadCfgWord - read a 16 bit value from pci config space - * - * Description: - * This routine reads a 16 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U16 *pVal) /* pointer to store the read value */ -{ - pci_read_config_word(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgWord */ - - -/***************************************************************************** - * - * SkPciReadCfgByte - read a 8 bit value from pci config space - * - * Description: - * This routine reads a 8 bit value from the pci configuration - * space. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciReadCfgByte( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U8 *pVal) /* pointer to store the read value */ -{ - pci_read_config_byte(pAC->PciDev, PciAddr, pVal); - return(0); -} /* SkPciReadCfgByte */ - - -/***************************************************************************** - * - * SkPciWriteCfgWord - write a 16 bit value to pci config space - * - * Description: - * This routine writes a 16 bit value to the pci configuration - * space. The flag PciConfigUp indicates whether the config space - * is accesible or must be set up first. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciWriteCfgWord( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U16 Val) /* pointer to store the read value */ -{ - pci_write_config_word(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgWord */ - - -/***************************************************************************** - * - * SkPciWriteCfgWord - write a 8 bit value to pci config space - * - * Description: - * This routine writes a 8 bit value to the pci configuration - * space. The flag PciConfigUp indicates whether the config space - * is accesible or must be set up first. - * - * Returns: - * 0 - indicate everything worked ok. - * != 0 - error indication - */ -int SkPciWriteCfgByte( -SK_AC *pAC, /* Adapter Control structure pointer */ -int PciAddr, /* PCI register address */ -SK_U8 Val) /* pointer to store the read value */ -{ - pci_write_config_byte(pAC->PciDev, PciAddr, Val); - return(0); -} /* SkPciWriteCfgByte */ - - -/***************************************************************************** - * - * SkDrvEvent - handle driver events - * - * Description: - * This function handles events from all modules directed to the driver - * - * Context: - * Is called under protection of slow path lock. - * - * Returns: - * 0 if everything ok - * < 0 on error - * - */ -int SkDrvEvent( -SK_AC *pAC, /* pointer to adapter context */ -SK_IOC IoC, /* io-context */ -SK_U32 Event, /* event-id */ -SK_EVPARA Param) /* event-parameter */ -{ -SK_MBUF *pRlmtMbuf; /* pointer to a rlmt-mbuf structure */ -struct sk_buff *pMsg; /* pointer to a message block */ -int FromPort; /* the port from which we switch away */ -int ToPort; /* the port we switch to */ -SK_EVPARA NewPara; /* parameter for further events */ -int Stat; -unsigned long Flags; -SK_BOOL DualNet; - - switch (Event) { - case SK_DRV_ADAP_FAIL: - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("ADAPTER FAIL EVENT\n")); - printk("%s: Adapter failed.\n", pAC->dev[0]->name); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - /* cgoos */ - break; - case SK_DRV_PORT_FAIL: - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT FAIL EVENT, Port: %d\n", FromPort)); - if (FromPort == 0) { - printk("%s: Port A failed.\n", pAC->dev[0]->name); - } else { - printk("%s: Port B failed.\n", pAC->dev[1]->name); - } - /* cgoos */ - break; - case SK_DRV_PORT_RESET: /* SK_U32 PortIdx */ - /* action list 4 */ - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT RESET EVENT, Port: %d ", FromPort)); - NewPara.Para64 = FromPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_HARD_RST); - netif_carrier_off(pAC->dev[Param.Para32[0]]); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - /* clear rx ring from received frames */ - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); - - ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - /* tschilling: Handling of return value inserted. */ - if (SkGeInitPort(pAC, IoC, FromPort)) { - if (FromPort == 0) { - printk("%s: SkGeInitPort A failed.\n", pAC->dev[0]->name); - } else { - printk("%s: SkGeInitPort B failed.\n", pAC->dev[1]->name); - } - } - SkAddrMcUpdate(pAC,IoC, FromPort); - PortReInitBmu(pAC, FromPort); - SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); - ClearAndStartRx(pAC, FromPort); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - break; - case SK_DRV_NET_UP: /* SK_U32 PortIdx */ - { struct net_device *dev = pAC->dev[Param.Para32[0]]; - /* action list 5 */ - FromPort = Param.Para32[0]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("NET UP EVENT, Port: %d ", Param.Para32[0])); - /* Mac update */ - SkAddrMcUpdate(pAC,IoC, FromPort); - - if (DoPrintInterfaceChange) { - printk("%s: network connection up using" - " port %c\n", pAC->dev[Param.Para32[0]]->name, 'A'+Param.Para32[0]); - - /* tschilling: Values changed according to LinkSpeedUsed. */ - Stat = pAC->GIni.GP[FromPort].PLinkSpeedUsed; - if (Stat == SK_LSPEED_STAT_10MBPS) { - printk(" speed: 10\n"); - } else if (Stat == SK_LSPEED_STAT_100MBPS) { - printk(" speed: 100\n"); - } else if (Stat == SK_LSPEED_STAT_1000MBPS) { - printk(" speed: 1000\n"); - } else { - printk(" speed: unknown\n"); - } - - - Stat = pAC->GIni.GP[FromPort].PLinkModeStatus; - if (Stat == SK_LMODE_STAT_AUTOHALF || - Stat == SK_LMODE_STAT_AUTOFULL) { - printk(" autonegotiation: yes\n"); - } - else { - printk(" autonegotiation: no\n"); - } - if (Stat == SK_LMODE_STAT_AUTOHALF || - Stat == SK_LMODE_STAT_HALF) { - printk(" duplex mode: half\n"); - } - else { - printk(" duplex mode: full\n"); - } - Stat = pAC->GIni.GP[FromPort].PFlowCtrlStatus; - if (Stat == SK_FLOW_STAT_REM_SEND ) { - printk(" flowctrl: remote send\n"); - } - else if (Stat == SK_FLOW_STAT_LOC_SEND ){ - printk(" flowctrl: local send\n"); - } - else if (Stat == SK_FLOW_STAT_SYMMETRIC ){ - printk(" flowctrl: symmetric\n"); - } - else { - printk(" flowctrl: none\n"); - } - - /* tschilling: Check against CopperType now. */ - if ((pAC->GIni.GICopperType == SK_TRUE) && - (pAC->GIni.GP[FromPort].PLinkSpeedUsed == - SK_LSPEED_STAT_1000MBPS)) { - Stat = pAC->GIni.GP[FromPort].PMSStatus; - if (Stat == SK_MS_STAT_MASTER ) { - printk(" role: master\n"); - } - else if (Stat == SK_MS_STAT_SLAVE ) { - printk(" role: slave\n"); - } - else { - printk(" role: ???\n"); - } - } - - /* - Display dim (dynamic interrupt moderation) - informations - */ - if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_STATIC) - printk(" irq moderation: static (%d ints/sec)\n", - pAC->DynIrqModInfo.MaxModIntsPerSec); - else if (pAC->DynIrqModInfo.IntModTypeSelect == C_INT_MOD_DYNAMIC) - printk(" irq moderation: dynamic (%d ints/sec)\n", - pAC->DynIrqModInfo.MaxModIntsPerSec); - else - printk(" irq moderation: disabled\n"); - - - printk(" scatter-gather: %s\n", - (dev->features & NETIF_F_SG) ? "enabled" : "disabled"); - printk(" tx-checksum: %s\n", - (dev->features & NETIF_F_IP_CSUM) ? "enabled" : "disabled"); - printk(" rx-checksum: %s\n", - pAC->RxPort[Param.Para32[0]].RxCsum ? "enabled" : "disabled"); - - } else { - DoPrintInterfaceChange = SK_TRUE; - } - - if ((Param.Para32[0] != pAC->ActivePort) && - (pAC->RlmtNets == 1)) { - NewPara.Para32[0] = pAC->ActivePort; - NewPara.Para32[1] = Param.Para32[0]; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_INTERN, - NewPara); - } - - /* Inform the world that link protocol is up. */ - netif_carrier_on(dev); - break; - } - case SK_DRV_NET_DOWN: /* SK_U32 Reason */ - /* action list 7 */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("NET DOWN EVENT ")); - if (DoPrintInterfaceChange) { - printk("%s: network connection down\n", - pAC->dev[Param.Para32[1]]->name); - } else { - DoPrintInterfaceChange = SK_TRUE; - } - netif_carrier_off(pAC->dev[Param.Para32[1]]); - break; - case SK_DRV_SWITCH_HARD: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT SWITCH HARD ")); - case SK_DRV_SWITCH_SOFT: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - /* action list 6 */ - printk("%s: switching to port %c\n", pAC->dev[0]->name, - 'A'+Param.Para32[1]); - case SK_DRV_SWITCH_INTERN: /* SK_U32 FromPortIdx SK_U32 ToPortIdx */ - FromPort = Param.Para32[0]; - ToPort = Param.Para32[1]; - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("PORT SWITCH EVENT, From: %d To: %d (Pref %d) ", - FromPort, ToPort, pAC->Rlmt.Net[0].PrefPort)); - NewPara.Para64 = FromPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - NewPara.Para64 = ToPort; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_XMAC_RESET, NewPara); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - SkGeStopPort(pAC, IoC, FromPort, SK_STOP_ALL, SK_SOFT_RST); - SkGeStopPort(pAC, IoC, ToPort, SK_STOP_ALL, SK_SOFT_RST); - spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - - ReceiveIrq(pAC, &pAC->RxPort[FromPort], SK_FALSE); /* clears rx ring */ - ReceiveIrq(pAC, &pAC->RxPort[ToPort], SK_FALSE); /* clears rx ring */ - - ClearTxRing(pAC, &pAC->TxPort[FromPort][TX_PRIO_LOW]); - ClearTxRing(pAC, &pAC->TxPort[ToPort][TX_PRIO_LOW]); - spin_lock_irqsave( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - spin_lock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - pAC->ActivePort = ToPort; -#if 0 - SetQueueSizes(pAC); -#else - /* tschilling: New common function with minimum size check. */ - DualNet = SK_FALSE; - if (pAC->RlmtNets == 2) { - DualNet = SK_TRUE; - } - - if (SkGeInitAssignRamToQueues( - pAC, - pAC->ActivePort, - DualNet)) { - spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - printk("SkGeInitAssignRamToQueues failed.\n"); - break; - } -#endif - /* tschilling: Handling of return values inserted. */ - if (SkGeInitPort(pAC, IoC, FromPort) || - SkGeInitPort(pAC, IoC, ToPort)) { - printk("%s: SkGeInitPort failed.\n", pAC->dev[0]->name); - } - if (Event == SK_DRV_SWITCH_SOFT) { - SkMacRxTxEnable(pAC, IoC, FromPort); - } - SkMacRxTxEnable(pAC, IoC, ToPort); - SkAddrSwap(pAC, IoC, FromPort, ToPort); - SkAddrMcUpdate(pAC, IoC, FromPort); - SkAddrMcUpdate(pAC, IoC, ToPort); - PortReInitBmu(pAC, FromPort); - PortReInitBmu(pAC, ToPort); - SkGePollTxD(pAC, IoC, FromPort, SK_TRUE); - SkGePollTxD(pAC, IoC, ToPort, SK_TRUE); - ClearAndStartRx(pAC, FromPort); - ClearAndStartRx(pAC, ToPort); - spin_unlock(&pAC->TxPort[ToPort][TX_PRIO_LOW].TxDesRingLock); - spin_unlock_irqrestore( - &pAC->TxPort[FromPort][TX_PRIO_LOW].TxDesRingLock, - Flags); - break; - case SK_DRV_RLMT_SEND: /* SK_MBUF *pMb */ - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("RLS ")); - pRlmtMbuf = (SK_MBUF*) Param.pParaPtr; - pMsg = (struct sk_buff*) pRlmtMbuf->pOs; - skb_put(pMsg, pRlmtMbuf->Length); - if (XmitFrame(pAC, &pAC->TxPort[pRlmtMbuf->PortIdx][TX_PRIO_LOW], - pMsg) < 0) - - DEV_KFREE_SKB_ANY(pMsg); - break; - case SK_DRV_TIMER: - if (Param.Para32[0] == SK_DRV_MODERATION_TIMER) { - /* - ** expiration of the moderation timer implies that - ** dynamic moderation is to be applied - */ - SkDimStartModerationTimer(pAC); - SkDimModerate(pAC); - if (pAC->DynIrqModInfo.DisplayStats) { - SkDimDisplayModerationSettings(pAC); - } - } else if (Param.Para32[0] == SK_DRV_RX_CLEANUP_TIMER) { - /* - ** check if we need to check for descriptors which - ** haven't been handled the last millisecs - */ - StartDrvCleanupTimer(pAC); - if (pAC->GIni.GIMacsFound == 2) { - ReceiveIrq(pAC, &pAC->RxPort[1], SK_FALSE); - } - ReceiveIrq(pAC, &pAC->RxPort[0], SK_FALSE); - } else { - printk("Expiration of unknown timer\n"); - } - break; - default: - break; - } - SK_DBG_MSG(NULL, SK_DBGMOD_DRV, SK_DBGCAT_DRV_EVENT, - ("END EVENT ")); - - return (0); -} /* SkDrvEvent */ - - -/***************************************************************************** - * - * SkErrorLog - log errors - * - * Description: - * This function logs errors to the system buffer and to the console - * - * Returns: - * 0 if everything ok - * < 0 on error - * - */ -void SkErrorLog( -SK_AC *pAC, -int ErrClass, -int ErrNum, -char *pErrorMsg) -{ -char ClassStr[80]; - - switch (ErrClass) { - case SK_ERRCL_OTHER: - strcpy(ClassStr, "Other error"); - break; - case SK_ERRCL_CONFIG: - strcpy(ClassStr, "Configuration error"); - break; - case SK_ERRCL_INIT: - strcpy(ClassStr, "Initialization error"); - break; - case SK_ERRCL_NORES: - strcpy(ClassStr, "Out of resources error"); - break; - case SK_ERRCL_SW: - strcpy(ClassStr, "internal Software error"); - break; - case SK_ERRCL_HW: - strcpy(ClassStr, "Hardware failure"); - break; - case SK_ERRCL_COMM: - strcpy(ClassStr, "Communication error"); - break; - } - printk(KERN_INFO "%s: -- ERROR --\n Class: %s\n" - " Nr: 0x%x\n Msg: %s\n", pAC->dev[0]->name, - ClassStr, ErrNum, pErrorMsg); - -} /* SkErrorLog */ - -#ifdef SK_DIAG_SUPPORT - -/***************************************************************************** - * - * SkDrvEnterDiagMode - handles DIAG attach request - * - * Description: - * Notify the kernel to NOT access the card any longer due to DIAG - * Deinitialize the Card - * - * Returns: - * int - */ -int SkDrvEnterDiagMode( -SK_AC *pAc) /* pointer to adapter context */ -{ - DEV_NET *pNet = netdev_priv(pAc->dev[0]); - SK_AC *pAC = pNet->pAC; - - SK_MEMCPY(&(pAc->PnmiBackup), &(pAc->PnmiStruct), - sizeof(SK_PNMI_STRUCT_DATA)); - - pAC->DiagModeActive = DIAG_ACTIVE; - if (pAC->BoardLevel > SK_INIT_DATA) { - if (netif_running(pAC->dev[0])) { - pAC->WasIfUp[0] = SK_TRUE; - pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ - DoPrintInterfaceChange = SK_FALSE; - SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ - } else { - pAC->WasIfUp[0] = SK_FALSE; - } - if (pNet != netdev_priv(pAC->dev[1])) { - pNet = netdev_priv(pAC->dev[1]); - if (netif_running(pAC->dev[1])) { - pAC->WasIfUp[1] = SK_TRUE; - pAC->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ - DoPrintInterfaceChange = SK_FALSE; - SkDrvDeInitAdapter(pAC, 1); /* do SkGeClose */ - } else { - pAC->WasIfUp[1] = SK_FALSE; - } - } - pAC->BoardLevel = SK_INIT_DATA; - } - return(0); -} - -/***************************************************************************** - * - * SkDrvLeaveDiagMode - handles DIAG detach request - * - * Description: - * Notify the kernel to may access the card again after use by DIAG - * Initialize the Card - * - * Returns: - * int - */ -int SkDrvLeaveDiagMode( -SK_AC *pAc) /* pointer to adapter control context */ -{ - SK_MEMCPY(&(pAc->PnmiStruct), &(pAc->PnmiBackup), - sizeof(SK_PNMI_STRUCT_DATA)); - pAc->DiagModeActive = DIAG_NOTACTIVE; - pAc->Pnmi.DiagAttached = SK_DIAG_IDLE; - if (pAc->WasIfUp[0] == SK_TRUE) { - pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAc, 0); /* first device */ - } - if (pAc->WasIfUp[1] == SK_TRUE) { - pAc->DiagFlowCtrl = SK_TRUE; /* for SkGeClose */ - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAc, 1); /* second device */ - } - return(0); -} - -/***************************************************************************** - * - * ParseDeviceNbrFromSlotName - Evaluate PCI device number - * - * Description: - * This function parses the PCI slot name information string and will - * retrieve the devcie number out of it. The slot_name maintianed by - * linux is in the form of '02:0a.0', whereas the first two characters - * represent the bus number in hex (in the sample above this is - * pci bus 0x02) and the next two characters the device number (0x0a). - * - * Returns: - * SK_U32: The device number from the PCI slot name - */ - -static SK_U32 ParseDeviceNbrFromSlotName( -const char *SlotName) /* pointer to pci slot name eg. '02:0a.0' */ -{ - char *CurrCharPos = (char *) SlotName; - int FirstNibble = -1; - int SecondNibble = -1; - SK_U32 Result = 0; - - while (*CurrCharPos != '\0') { - if (*CurrCharPos == ':') { - while (*CurrCharPos != '.') { - CurrCharPos++; - if ( (*CurrCharPos >= '0') && - (*CurrCharPos <= '9')) { - if (FirstNibble == -1) { - /* dec. value for '0' */ - FirstNibble = *CurrCharPos - 48; - } else { - SecondNibble = *CurrCharPos - 48; - } - } else if ( (*CurrCharPos >= 'a') && - (*CurrCharPos <= 'f') ) { - if (FirstNibble == -1) { - FirstNibble = *CurrCharPos - 87; - } else { - SecondNibble = *CurrCharPos - 87; - } - } else { - Result = 0; - } - } - - Result = FirstNibble; - Result = Result << 4; /* first nibble is higher one */ - Result = Result | SecondNibble; - } - CurrCharPos++; /* next character */ - } - return (Result); -} - -/**************************************************************************** - * - * SkDrvDeInitAdapter - deinitialize adapter (this function is only - * called if Diag attaches to that card) - * - * Description: - * Close initialized adapter. - * - * Returns: - * 0 - on success - * error code - on error - */ -static int SkDrvDeInitAdapter( -SK_AC *pAC, /* pointer to adapter context */ -int devNbr) /* what device is to be handled */ -{ - struct SK_NET_DEVICE *dev; - - dev = pAC->dev[devNbr]; - - /* On Linux 2.6 the network driver does NOT mess with reference - ** counts. The driver MUST be able to be unloaded at any time - ** due to the possibility of hotplug. - */ - if (SkGeClose(dev) != 0) { - return (-1); - } - return (0); - -} /* SkDrvDeInitAdapter() */ - -/**************************************************************************** - * - * SkDrvInitAdapter - Initialize adapter (this function is only - * called if Diag deattaches from that card) - * - * Description: - * Close initialized adapter. - * - * Returns: - * 0 - on success - * error code - on error - */ -static int SkDrvInitAdapter( -SK_AC *pAC, /* pointer to adapter context */ -int devNbr) /* what device is to be handled */ -{ - struct SK_NET_DEVICE *dev; - - dev = pAC->dev[devNbr]; - - if (SkGeOpen(dev) != 0) { - return (-1); - } - - /* - ** Use correct MTU size and indicate to kernel TX queue can be started - */ - if (SkGeChangeMtu(dev, dev->mtu) != 0) { - return (-1); - } - return (0); - -} /* SkDrvInitAdapter */ - -#endif - -#ifdef DEBUG -/****************************************************************************/ -/* "debug only" section *****************************************************/ -/****************************************************************************/ - - -/***************************************************************************** - * - * DumpMsg - print a frame - * - * Description: - * This function prints frames to the system logfile/to the console. - * - * Returns: N/A - * - */ -static void DumpMsg(struct sk_buff *skb, char *str) -{ - int msglen; - - if (skb == NULL) { - printk("DumpMsg(): NULL-Message\n"); - return; - } - - if (skb->data == NULL) { - printk("DumpMsg(): Message empty\n"); - return; - } - - msglen = skb->len; - if (msglen > 64) - msglen = 64; - - printk("--- Begin of message from %s , len %d (from %d) ----\n", str, msglen, skb->len); - - DumpData((char *)skb->data, msglen); - - printk("------- End of message ---------\n"); -} /* DumpMsg */ - - - -/***************************************************************************** - * - * DumpData - print a data area - * - * Description: - * This function prints a area of data to the system logfile/to the - * console. - * - * Returns: N/A - * - */ -static void DumpData(char *p, int size) -{ -register int i; -int haddr, addr; -char hex_buffer[180]; -char asc_buffer[180]; -char HEXCHAR[] = "0123456789ABCDEF"; - - addr = 0; - haddr = 0; - hex_buffer[0] = 0; - asc_buffer[0] = 0; - for (i=0; i < size; ) { - if (*p >= '0' && *p <='z') - asc_buffer[addr] = *p; - else - asc_buffer[addr] = '.'; - addr++; - asc_buffer[addr] = 0; - hex_buffer[haddr] = HEXCHAR[(*p & 0xf0) >> 4]; - haddr++; - hex_buffer[haddr] = HEXCHAR[*p & 0x0f]; - haddr++; - hex_buffer[haddr] = ' '; - haddr++; - hex_buffer[haddr] = 0; - p++; - i++; - if (i%16 == 0) { - printk("%s %s\n", hex_buffer, asc_buffer); - addr = 0; - haddr = 0; - } - } -} /* DumpData */ - - -/***************************************************************************** - * - * DumpLong - print a data area as long values - * - * Description: - * This function prints a area of data to the system logfile/to the - * console. - * - * Returns: N/A - * - */ -static void DumpLong(char *pc, int size) -{ -register int i; -int haddr, addr; -char hex_buffer[180]; -char asc_buffer[180]; -char HEXCHAR[] = "0123456789ABCDEF"; -long *p; -int l; - - addr = 0; - haddr = 0; - hex_buffer[0] = 0; - asc_buffer[0] = 0; - p = (long*) pc; - for (i=0; i < size; ) { - l = (long) *p; - hex_buffer[haddr] = HEXCHAR[(l >> 28) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 24) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 20) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 16) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 12) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 8) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[(l >> 4) & 0xf]; - haddr++; - hex_buffer[haddr] = HEXCHAR[l & 0x0f]; - haddr++; - hex_buffer[haddr] = ' '; - haddr++; - hex_buffer[haddr] = 0; - p++; - i++; - if (i%8 == 0) { - printk("%4x %s\n", (i-8)*4, hex_buffer); - haddr = 0; - } - } - printk("------------------------\n"); -} /* DumpLong */ - -#endif - -static int __devinit skge_probe_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - SK_AC *pAC; - DEV_NET *pNet = NULL; - struct net_device *dev = NULL; - static int boards_found = 0; - int error = -ENODEV; - int using_dac = 0; - char DeviceStr[80]; - - if (pci_enable_device(pdev)) - goto out; - - /* Configure DMA attributes. */ - if (sizeof(dma_addr_t) > sizeof(u32) && - !(error = pci_set_dma_mask(pdev, DMA_64BIT_MASK))) { - using_dac = 1; - error = pci_set_consistent_dma_mask(pdev, DMA_64BIT_MASK); - if (error < 0) { - printk(KERN_ERR "sk98lin %s unable to obtain 64 bit DMA " - "for consistent allocations\n", pci_name(pdev)); - goto out_disable_device; - } - } else { - error = pci_set_dma_mask(pdev, DMA_32BIT_MASK); - if (error) { - printk(KERN_ERR "sk98lin %s no usable DMA configuration\n", - pci_name(pdev)); - goto out_disable_device; - } - } - - error = -ENOMEM; - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "sk98lin: unable to allocate etherdev " - "structure!\n"); - goto out_disable_device; - } - - pNet = netdev_priv(dev); - pNet->pAC = kzalloc(sizeof(SK_AC), GFP_KERNEL); - if (!pNet->pAC) { - printk(KERN_ERR "sk98lin: unable to allocate adapter " - "structure!\n"); - goto out_free_netdev; - } - - pAC = pNet->pAC; - pAC->PciDev = pdev; - - pAC->dev[0] = dev; - pAC->dev[1] = dev; - pAC->CheckQueue = SK_FALSE; - - dev->irq = pdev->irq; - - error = SkGeInitPCI(pAC); - if (error) { - printk(KERN_ERR "sk98lin: PCI setup failed: %i\n", error); - goto out_free_netdev; - } - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; -#ifdef CONFIG_NET_POLL_CONTROLLER - dev->poll_controller = &SkGePollController; -#endif - SET_NETDEV_DEV(dev, &pdev->dev); - SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); - - /* Use only if yukon hardware */ - if (pAC->ChipsetType) { -#ifdef USE_SK_TX_CHECKSUM - dev->features |= NETIF_F_IP_CSUM; -#endif -#ifdef SK_ZEROCOPY - dev->features |= NETIF_F_SG; -#endif -#ifdef USE_SK_RX_CHECKSUM - pAC->RxPort[0].RxCsum = 1; -#endif - } - - if (using_dac) - dev->features |= NETIF_F_HIGHDMA; - - pAC->Index = boards_found++; - - error = SkGeBoardInit(dev, pAC); - if (error) - goto out_free_netdev; - - /* Read Adapter name from VPD */ - if (ProductStr(pAC, DeviceStr, sizeof(DeviceStr)) != 0) { - error = -EIO; - printk(KERN_ERR "sk98lin: Could not read VPD data.\n"); - goto out_free_resources; - } - - /* Register net device */ - error = register_netdev(dev); - if (error) { - printk(KERN_ERR "sk98lin: Could not register device.\n"); - goto out_free_resources; - } - - /* Print adapter specific string from vpd */ - printk("%s: %s\n", dev->name, DeviceStr); - - /* Print configuration settings */ - printk(" PrefPort:%c RlmtMode:%s\n", - 'A' + pAC->Rlmt.Net[0].Port[pAC->Rlmt.Net[0].PrefPort]->PortNumber, - (pAC->RlmtMode==0) ? "Check Link State" : - ((pAC->RlmtMode==1) ? "Check Link State" : - ((pAC->RlmtMode==3) ? "Check Local Port" : - ((pAC->RlmtMode==7) ? "Check Segmentation" : - ((pAC->RlmtMode==17) ? "Dual Check Link State" :"Error"))))); - - SkGeYellowLED(pAC, pAC->IoBase, 1); - - memcpy(&dev->dev_addr, &pAC->Addr.Net[0].CurrentMacAddress, 6); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - pNet->PortNr = 0; - pNet->NetNr = 0; - - boards_found++; - - pci_set_drvdata(pdev, dev); - - /* More then one port found */ - if ((pAC->GIni.GIMacsFound == 2 ) && (pAC->RlmtNets == 2)) { - dev = alloc_etherdev(sizeof(DEV_NET)); - if (!dev) { - printk(KERN_ERR "sk98lin: unable to allocate etherdev " - "structure!\n"); - goto single_port; - } - - pNet = netdev_priv(dev); - pNet->PortNr = 1; - pNet->NetNr = 1; - pNet->pAC = pAC; - - dev->open = &SkGeOpen; - dev->stop = &SkGeClose; - dev->hard_start_xmit = &SkGeXmit; - dev->get_stats = &SkGeStats; - dev->set_multicast_list = &SkGeSetRxMode; - dev->set_mac_address = &SkGeSetMacAddr; - dev->do_ioctl = &SkGeIoctl; - dev->change_mtu = &SkGeChangeMtu; - SET_NETDEV_DEV(dev, &pdev->dev); - SET_ETHTOOL_OPS(dev, &SkGeEthtoolOps); - - if (pAC->ChipsetType) { -#ifdef USE_SK_TX_CHECKSUM - dev->features |= NETIF_F_IP_CSUM; -#endif -#ifdef SK_ZEROCOPY - dev->features |= NETIF_F_SG; -#endif -#ifdef USE_SK_RX_CHECKSUM - pAC->RxPort[1].RxCsum = 1; -#endif - } - - if (using_dac) - dev->features |= NETIF_F_HIGHDMA; - - error = register_netdev(dev); - if (error) { - printk(KERN_ERR "sk98lin: Could not register device" - " for second port. (%d)\n", error); - free_netdev(dev); - goto single_port; - } - - pAC->dev[1] = dev; - memcpy(&dev->dev_addr, - &pAC->Addr.Net[1].CurrentMacAddress, 6); - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); - - printk("%s: %s\n", dev->name, DeviceStr); - printk(" PrefPort:B RlmtMode:Dual Check Link State\n"); - } - -single_port: - - /* Save the hardware revision */ - pAC->HWRevision = (((pAC->GIni.GIPciHwRev >> 4) & 0x0F)*10) + - (pAC->GIni.GIPciHwRev & 0x0F); - - /* Set driver globals */ - pAC->Pnmi.pDriverFileName = DRIVER_FILE_NAME; - pAC->Pnmi.pDriverReleaseDate = DRIVER_REL_DATE; - - memset(&pAC->PnmiBackup, 0, sizeof(SK_PNMI_STRUCT_DATA)); - memcpy(&pAC->PnmiBackup, &pAC->PnmiStruct, sizeof(SK_PNMI_STRUCT_DATA)); - - return 0; - - out_free_resources: - FreeResources(dev); - out_free_netdev: - free_netdev(dev); - out_disable_device: - pci_disable_device(pdev); - out: - return error; -} - -static void __devexit skge_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - struct net_device *otherdev = pAC->dev[1]; - - unregister_netdev(dev); - - SkGeYellowLED(pAC, pAC->IoBase, 0); - - if (pAC->BoardLevel == SK_INIT_RUN) { - SK_EVPARA EvPara; - unsigned long Flags; - - /* board is still alive */ - spin_lock_irqsave(&pAC->SlowPathLock, Flags); - EvPara.Para32[0] = 0; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - EvPara.Para32[0] = 1; - EvPara.Para32[1] = -1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STOP, EvPara); - SkEventDispatcher(pAC, pAC->IoBase); - /* disable interrupts */ - SK_OUT32(pAC->IoBase, B0_IMSK, 0); - SkGeDeInit(pAC, pAC->IoBase); - spin_unlock_irqrestore(&pAC->SlowPathLock, Flags); - pAC->BoardLevel = SK_INIT_DATA; - /* We do NOT check here, if IRQ was pending, of course*/ - } - - if (pAC->BoardLevel == SK_INIT_IO) { - /* board is still alive */ - SkGeDeInit(pAC, pAC->IoBase); - pAC->BoardLevel = SK_INIT_DATA; - } - - FreeResources(dev); - free_netdev(dev); - if (otherdev != dev) - free_netdev(otherdev); - kfree(pAC); -} - -#ifdef CONFIG_PM -static int skge_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *dev = pci_get_drvdata(pdev); - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - struct net_device *otherdev = pAC->dev[1]; - - if (netif_running(dev)) { - netif_carrier_off(dev); - DoPrintInterfaceChange = SK_FALSE; - SkDrvDeInitAdapter(pAC, 0); /* performs SkGeClose */ - netif_device_detach(dev); - } - if (otherdev != dev) { - if (netif_running(otherdev)) { - netif_carrier_off(otherdev); - DoPrintInterfaceChange = SK_FALSE; - SkDrvDeInitAdapter(pAC, 1); /* performs SkGeClose */ - netif_device_detach(otherdev); - } - } - - pci_save_state(pdev); - pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); - if (pAC->AllocFlag & SK_ALLOC_IRQ) { - free_irq(dev->irq, dev); - } - pci_disable_device(pdev); - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int skge_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - DEV_NET *pNet = netdev_priv(dev); - SK_AC *pAC = pNet->pAC; - struct net_device *otherdev = pAC->dev[1]; - int ret; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - ret = pci_enable_device(pdev); - if (ret) { - printk(KERN_WARNING "sk98lin: unable to enable device %s " - "in resume\n", dev->name); - goto err_out; - } - pci_set_master(pdev); - if (pAC->GIni.GIMacsFound == 2) - ret = request_irq(dev->irq, SkGeIsr, IRQF_SHARED, "sk98lin", dev); - else - ret = request_irq(dev->irq, SkGeIsrOnePort, IRQF_SHARED, "sk98lin", dev); - if (ret) { - printk(KERN_WARNING "sk98lin: unable to acquire IRQ %d\n", dev->irq); - ret = -EBUSY; - goto err_out_disable_pdev; - } - - netif_device_attach(dev); - if (netif_running(dev)) { - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAC, 0); /* first device */ - } - if (otherdev != dev) { - netif_device_attach(otherdev); - if (netif_running(otherdev)) { - DoPrintInterfaceChange = SK_FALSE; - SkDrvInitAdapter(pAC, 1); /* second device */ - } - } - - return 0; - -err_out_disable_pdev: - pci_disable_device(pdev); -err_out: - pAC->AllocFlag &= ~SK_ALLOC_IRQ; - dev->irq = 0; - return ret; -} -#else -#define skge_suspend NULL -#define skge_resume NULL -#endif - -static struct pci_device_id skge_pci_tbl[] = { -#ifdef SK98LIN_ALL_DEVICES - { PCI_VENDOR_ID_3COM, 0x1700, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_3COM, 0x80eb, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -#endif -#ifdef GENESIS - /* Generic SysKonnect SK-98xx Gigabit Ethernet Server Adapter */ - { PCI_VENDOR_ID_SYSKONNECT, 0x4300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -#endif - /* Generic SysKonnect SK-98xx V2.0 Gigabit Ethernet Adapter */ - { PCI_VENDOR_ID_SYSKONNECT, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -#ifdef SK98LIN_ALL_DEVICES -/* DLink card does not have valid VPD so this driver gags - * { PCI_VENDOR_ID_DLINK, 0x4c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - */ - { PCI_VENDOR_ID_MARVELL, 0x4320, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_MARVELL, 0x5005, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_CNET, 0x434e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015, }, - { PCI_VENDOR_ID_LINKSYS, 0x1064, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, -#endif - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, skge_pci_tbl); - -static struct pci_driver skge_driver = { - .name = "sk98lin", - .id_table = skge_pci_tbl, - .probe = skge_probe_one, - .remove = __devexit_p(skge_remove_one), - .suspend = skge_suspend, - .resume = skge_resume, -}; - -static int __init skge_init(void) -{ - printk(KERN_NOTICE "sk98lin: driver has been replaced by the skge driver" - " and is scheduled for removal\n"); - - return pci_register_driver(&skge_driver); -} - -static void __exit skge_exit(void) -{ - pci_unregister_driver(&skge_driver); -} - -module_init(skge_init); -module_exit(skge_exit); diff --git a/drivers/net/sk98lin/skgehwt.c b/drivers/net/sk98lin/skgehwt.c deleted file mode 100644 index db670993c2df..000000000000 --- a/drivers/net/sk98lin/skgehwt.c +++ /dev/null @@ -1,171 +0,0 @@ -/****************************************************************************** - * - * Name: skgehwt.c - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.15 $ - * Date: $Date: 2003/09/16 13:41:23 $ - * Purpose: Hardware Timer - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * Event queue and dispatcher - */ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skgehwt.c,v 1.15 2003/09/16 13:41:23 rschmidt Exp $ (C) Marvell."; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - * Hardware Timer function queue management. - */ -intro() -{} -#endif - -/* - * Prototypes of local functions. - */ -#define SK_HWT_MAX (65000) - -/* correction factor */ -#define SK_HWT_FAC (1000 * (SK_U32)pAC->GIni.GIHstClkFact / 100) - -/* - * Initialize hardware timer. - * - * Must be called during init level 1. - */ -void SkHwtInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - pAC->Hwt.TStart = 0 ; - pAC->Hwt.TStop = 0 ; - pAC->Hwt.TActive = SK_FALSE; - - SkHwtStop(pAC, Ioc); -} - -/* - * - * Start hardware timer (clock ticks are 16us). - * - */ -void SkHwtStart( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_U32 Time) /* Time in units of 16us to load the timer with. */ -{ - SK_U32 Cnt; - - if (Time > SK_HWT_MAX) - Time = SK_HWT_MAX; - - pAC->Hwt.TStart = Time; - pAC->Hwt.TStop = 0L; - - Cnt = Time; - - /* - * if time < 16 us - * time = 16 us - */ - if (!Cnt) { - Cnt++; - } - - SK_OUT32(Ioc, B2_TI_INI, Cnt * SK_HWT_FAC); - - SK_OUT16(Ioc, B2_TI_CTRL, TIM_START); /* Start timer. */ - - pAC->Hwt.TActive = SK_TRUE; -} - -/* - * Stop hardware timer. - * and clear the timer IRQ - */ -void SkHwtStop( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SK_OUT16(Ioc, B2_TI_CTRL, TIM_STOP); - - SK_OUT16(Ioc, B2_TI_CTRL, TIM_CLR_IRQ); - - pAC->Hwt.TActive = SK_FALSE; -} - - -/* - * Stop hardware timer and read time elapsed since last start. - * - * returns - * The elapsed time since last start in units of 16us. - * - */ -SK_U32 SkHwtRead( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SK_U32 TRead; - SK_U32 IStatus; - - if (pAC->Hwt.TActive) { - - SkHwtStop(pAC, Ioc); - - SK_IN32(Ioc, B2_TI_VAL, &TRead); - TRead /= SK_HWT_FAC; - - SK_IN32(Ioc, B0_ISRC, &IStatus); - - /* Check if timer expired (or wraped around) */ - if ((TRead > pAC->Hwt.TStart) || (IStatus & IS_TIMINT)) { - - SkHwtStop(pAC, Ioc); - - pAC->Hwt.TStop = pAC->Hwt.TStart; - } - else { - - pAC->Hwt.TStop = pAC->Hwt.TStart - TRead; - } - } - return(pAC->Hwt.TStop); -} - -/* - * interrupt source= timer - */ -void SkHwtIsr( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - SkHwtStop(pAC, Ioc); - - pAC->Hwt.TStop = pAC->Hwt.TStart; - - SkTimerDone(pAC, Ioc); -} - -/* End of file */ diff --git a/drivers/net/sk98lin/skgeinit.c b/drivers/net/sk98lin/skgeinit.c deleted file mode 100644 index 67f1d6a5c15d..000000000000 --- a/drivers/net/sk98lin/skgeinit.c +++ /dev/null @@ -1,2005 +0,0 @@ -/****************************************************************************** - * - * Name: skgeinit.c - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.97 $ - * Date: $Date: 2003/10/02 16:45:31 $ - * Purpose: Contains functions to initialize the adapter - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* global variables ***********************************************************/ - -/* local variables ************************************************************/ - -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skgeinit.c,v 1.97 2003/10/02 16:45:31 rschmidt Exp $ (C) Marvell."; -#endif - -struct s_QOffTab { - int RxQOff; /* Receive Queue Address Offset */ - int XsQOff; /* Sync Tx Queue Address Offset */ - int XaQOff; /* Async Tx Queue Address Offset */ -}; -static struct s_QOffTab QOffTab[] = { - {Q_R1, Q_XS1, Q_XA1}, {Q_R2, Q_XS2, Q_XA2} -}; - -struct s_Config { - char ScanString[8]; - SK_U32 Value; -}; - -static struct s_Config OemConfig = { - {'O','E','M','_','C','o','n','f'}, -#ifdef SK_OEM_CONFIG - OEM_CONFIG_VALUE, -#else - 0, -#endif -}; - -/****************************************************************************** - * - * SkGePollTxD() - Enable / Disable Descriptor Polling of TxD Rings - * - * Description: - * Enable or disable the descriptor polling of the transmit descriptor - * ring(s) (TxD) for port 'Port'. - * The new configuration is *not* saved over any SkGeStopPort() and - * SkGeInitPort() calls. - * - * Returns: - * nothing - */ -void SkGePollTxD( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL PollTxD) /* SK_TRUE (enable pol.), SK_FALSE (disable pol.) */ -{ - SK_GEPORT *pPrt; - SK_U32 DWord; - - pPrt = &pAC->GIni.GP[Port]; - - DWord = (SK_U32)(PollTxD ? CSR_ENA_POL : CSR_DIS_POL); - - if (pPrt->PXSQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), DWord); - } - - if (pPrt->PXAQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), DWord); - } -} /* SkGePollTxD */ - - -/****************************************************************************** - * - * SkGeYellowLED() - Switch the yellow LED on or off. - * - * Description: - * Switch the yellow LED on or off. - * - * Note: - * This function may be called any time after SkGeInit(Level 1). - * - * Returns: - * nothing - */ -void SkGeYellowLED( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int State) /* yellow LED state, 0 = OFF, 0 != ON */ -{ - if (State == 0) { - /* Switch yellow LED OFF */ - SK_OUT8(IoC, B0_LED, LED_STAT_OFF); - } - else { - /* Switch yellow LED ON */ - SK_OUT8(IoC, B0_LED, LED_STAT_ON); - } -} /* SkGeYellowLED */ - - -#if (!defined(SK_SLIM) || defined(GENESIS)) -/****************************************************************************** - * - * SkGeXmitLED() - Modify the Operational Mode of a transmission LED. - * - * Description: - * The Rx or Tx LED which is specified by 'Led' will be - * enabled, disabled or switched on in test mode. - * - * Note: - * 'Led' must contain the address offset of the LEDs INI register. - * - * Usage: - * SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); - * - * Returns: - * nothing - */ -void SkGeXmitLED( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Led, /* offset to the LED Init Value register */ -int Mode) /* Mode may be SK_LED_DIS, SK_LED_ENA, SK_LED_TST */ -{ - SK_U32 LedIni; - - switch (Mode) { - case SK_LED_ENA: - LedIni = SK_XMIT_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; - SK_OUT32(IoC, Led + XMIT_LED_INI, LedIni); - SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START); - break; - case SK_LED_TST: - SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_ON); - SK_OUT32(IoC, Led + XMIT_LED_CNT, 100); - SK_OUT8(IoC, Led + XMIT_LED_CTRL, LED_START); - break; - case SK_LED_DIS: - default: - /* - * Do NOT stop the LED Timer here. The LED might be - * in on state. But it needs to go off. - */ - SK_OUT32(IoC, Led + XMIT_LED_CNT, 0); - SK_OUT8(IoC, Led + XMIT_LED_TST, LED_T_OFF); - break; - } - - /* - * 1000BT: The Transmit LED is driven by the PHY. - * But the default LED configuration is used for - * Level One and Broadcom PHYs. - * (Broadcom: It may be that PHY_B_PEC_EN_LTR has to be set.) - * (In this case it has to be added here. But we will see. XXX) - */ -} /* SkGeXmitLED */ -#endif /* !SK_SLIM || GENESIS */ - - -/****************************************************************************** - * - * DoCalcAddr() - Calculates the start and the end address of a queue. - * - * Description: - * This function calculates the start and the end address of a queue. - * Afterwards the 'StartVal' is incremented to the next start position. - * If the port is already initialized the calculated values - * will be checked against the configured values and an - * error will be returned, if they are not equal. - * If the port is not initialized the values will be written to - * *StartAdr and *EndAddr. - * - * Returns: - * 0: success - * 1: configuration error - */ -static int DoCalcAddr( -SK_AC *pAC, /* adapter context */ -SK_GEPORT SK_FAR *pPrt, /* port index */ -int QuSize, /* size of the queue to configure in kB */ -SK_U32 SK_FAR *StartVal, /* start value for address calculation */ -SK_U32 SK_FAR *QuStartAddr,/* start addr to calculate */ -SK_U32 SK_FAR *QuEndAddr) /* end address to calculate */ -{ - SK_U32 EndVal; - SK_U32 NextStart; - int Rtv; - - Rtv = 0; - if (QuSize == 0) { - EndVal = *StartVal; - NextStart = EndVal; - } - else { - EndVal = *StartVal + ((SK_U32)QuSize * 1024) - 1; - NextStart = EndVal + 1; - } - - if (pPrt->PState >= SK_PRT_INIT) { - if (*StartVal != *QuStartAddr || EndVal != *QuEndAddr) { - Rtv = 1; - } - } - else { - *QuStartAddr = *StartVal; - *QuEndAddr = EndVal; - } - - *StartVal = NextStart; - return(Rtv); -} /* DoCalcAddr */ - -/****************************************************************************** - * - * SkGeInitAssignRamToQueues() - allocate default queue sizes - * - * Description: - * This function assigns the memory to the different queues and ports. - * When DualNet is set to SK_TRUE all ports get the same amount of memory. - * Otherwise the first port gets most of the memory and all the - * other ports just the required minimum. - * This function can only be called when pAC->GIni.GIRamSize and - * pAC->GIni.GIMacsFound have been initialized, usually this happens - * at init level 1 - * - * Returns: - * 0 - ok - * 1 - invalid input values - * 2 - not enough memory - */ - -int SkGeInitAssignRamToQueues( -SK_AC *pAC, /* Adapter context */ -int ActivePort, /* Active Port in RLMT mode */ -SK_BOOL DualNet) /* adapter context */ -{ - int i; - int UsedKilobytes; /* memory already assigned */ - int ActivePortKilobytes; /* memory available for active port */ - SK_GEPORT *pGePort; - - UsedKilobytes = 0; - - if (ActivePort >= pAC->GIni.GIMacsFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInitAssignRamToQueues: ActivePort (%d) invalid\n", - ActivePort)); - return(1); - } - if (((pAC->GIni.GIMacsFound * (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE)) + - ((RAM_QUOTA_SYNC == 0) ? 0 : SK_MIN_TXQ_SIZE)) > pAC->GIni.GIRamSize) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInitAssignRamToQueues: Not enough memory (%d)\n", - pAC->GIni.GIRamSize)); - return(2); - } - - if (DualNet) { - /* every port gets the same amount of memory */ - ActivePortKilobytes = pAC->GIni.GIRamSize / pAC->GIni.GIMacsFound; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - pGePort = &pAC->GIni.GP[i]; - - /* take away the minimum memory for active queues */ - ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); - - /* receive queue gets the minimum + 80% of the rest */ - pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB(( - ActivePortKilobytes * (unsigned long) RAM_QUOTA_RX) / 100)) - + SK_MIN_RXQ_SIZE; - - ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); - - /* synchronous transmit queue */ - pGePort->PXSQSize = 0; - - /* asynchronous transmit queue */ - pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes + - SK_MIN_TXQ_SIZE); - } - } - else { - /* Rlmt Mode or single link adapter */ - - /* Set standby queue size defaults for all standby ports */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - if (i != ActivePort) { - pGePort = &pAC->GIni.GP[i]; - - pGePort->PRxQSize = SK_MIN_RXQ_SIZE; - pGePort->PXAQSize = SK_MIN_TXQ_SIZE; - pGePort->PXSQSize = 0; - - /* Count used RAM */ - UsedKilobytes += pGePort->PRxQSize + pGePort->PXAQSize; - } - } - /* what's left? */ - ActivePortKilobytes = pAC->GIni.GIRamSize - UsedKilobytes; - - /* assign it to the active port */ - /* first take away the minimum memory */ - ActivePortKilobytes -= (SK_MIN_RXQ_SIZE + SK_MIN_TXQ_SIZE); - pGePort = &pAC->GIni.GP[ActivePort]; - - /* receive queue get's the minimum + 80% of the rest */ - pGePort->PRxQSize = (int) (ROUND_QUEUE_SIZE_KB((ActivePortKilobytes * - (unsigned long) RAM_QUOTA_RX) / 100)) + SK_MIN_RXQ_SIZE; - - ActivePortKilobytes -= (pGePort->PRxQSize - SK_MIN_RXQ_SIZE); - - /* synchronous transmit queue */ - pGePort->PXSQSize = 0; - - /* asynchronous transmit queue */ - pGePort->PXAQSize = (int) ROUND_QUEUE_SIZE_KB(ActivePortKilobytes) + - SK_MIN_TXQ_SIZE; - } -#ifdef VCPU - VCPUprintf(0, "PRxQSize=%u, PXSQSize=%u, PXAQSize=%u\n", - pGePort->PRxQSize, pGePort->PXSQSize, pGePort->PXAQSize); -#endif /* VCPU */ - - return(0); -} /* SkGeInitAssignRamToQueues */ - -/****************************************************************************** - * - * SkGeCheckQSize() - Checks the Adapters Queue Size Configuration - * - * Description: - * This function verifies the Queue Size Configuration specified - * in the variables PRxQSize, PXSQSize, and PXAQSize of all - * used ports. - * This requirements must be fullfilled to have a valid configuration: - * - The size of all queues must not exceed GIRamSize. - * - The queue sizes must be specified in units of 8 kB. - * - The size of Rx queues of available ports must not be - * smaller than 16 kB. - * - The size of at least one Tx queue (synch. or asynch.) - * of available ports must not be smaller than 16 kB - * when Jumbo Frames are used. - * - The RAM start and end addresses must not be changed - * for ports which are already initialized. - * Furthermore SkGeCheckQSize() defines the Start and End Addresses - * of all ports and stores them into the HWAC port structure. - * - * Returns: - * 0: Queue Size Configuration valid - * 1: Queue Size Configuration invalid - */ -static int SkGeCheckQSize( -SK_AC *pAC, /* adapter context */ -int Port) /* port index */ -{ - SK_GEPORT *pPrt; - int i; - int Rtv; - int Rtv2; - SK_U32 StartAddr; -#ifndef SK_SLIM - int UsedMem; /* total memory used (max. found ports) */ -#endif - - Rtv = 0; - -#ifndef SK_SLIM - - UsedMem = 0; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - pPrt = &pAC->GIni.GP[i]; - - if ((pPrt->PRxQSize & QZ_UNITS) != 0 || - (pPrt->PXSQSize & QZ_UNITS) != 0 || - (pPrt->PXAQSize & QZ_UNITS) != 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); - return(1); - } - - if (i == Port && pPrt->PRxQSize < SK_MIN_RXQ_SIZE) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E011, SKERR_HWI_E011MSG); - return(1); - } - - /* - * the size of at least one Tx queue (synch. or asynch.) has to be > 0. - * if Jumbo Frames are used, this size has to be >= 16 kB. - */ - if ((i == Port && pPrt->PXSQSize == 0 && pPrt->PXAQSize == 0) || - (pAC->GIni.GIPortUsage == SK_JUMBO_LINK && - ((pPrt->PXSQSize > 0 && pPrt->PXSQSize < SK_MIN_TXQ_SIZE) || - (pPrt->PXAQSize > 0 && pPrt->PXAQSize < SK_MIN_TXQ_SIZE)))) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E023, SKERR_HWI_E023MSG); - return(1); - } - - UsedMem += pPrt->PRxQSize + pPrt->PXSQSize + pPrt->PXAQSize; - } - - if (UsedMem > pAC->GIni.GIRamSize) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E012, SKERR_HWI_E012MSG); - return(1); - } -#endif /* !SK_SLIM */ - - /* Now start address calculation */ - StartAddr = pAC->GIni.GIRamOffs; - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - pPrt = &pAC->GIni.GP[i]; - - /* Calculate/Check values for the receive queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PRxQSize, &StartAddr, - &pPrt->PRxQRamStart, &pPrt->PRxQRamEnd); - Rtv |= Rtv2; - - /* Calculate/Check values for the synchronous Tx queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXSQSize, &StartAddr, - &pPrt->PXsQRamStart, &pPrt->PXsQRamEnd); - Rtv |= Rtv2; - - /* Calculate/Check values for the asynchronous Tx queue */ - Rtv2 = DoCalcAddr(pAC, pPrt, pPrt->PXAQSize, &StartAddr, - &pPrt->PXaQRamStart, &pPrt->PXaQRamEnd); - Rtv |= Rtv2; - - if (Rtv) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E013, SKERR_HWI_E013MSG); - return(1); - } - } - - return(0); -} /* SkGeCheckQSize */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkGeInitMacArb() - Initialize the MAC Arbiter - * - * Description: - * This function initializes the MAC Arbiter. - * It must not be called if there is still an - * initialized or active port. - * - * Returns: - * nothing - */ -static void SkGeInitMacArb( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_MA_TO_CTRL, MA_RST_CLR); - - /* configure timeout values */ - SK_OUT8(IoC, B3_MA_TOINI_RX1, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_RX2, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_TX1, SK_MAC_TO_53); - SK_OUT8(IoC, B3_MA_TOINI_TX2, SK_MAC_TO_53); - - SK_OUT8(IoC, B3_MA_RCINI_RX1, 0); - SK_OUT8(IoC, B3_MA_RCINI_RX2, 0); - SK_OUT8(IoC, B3_MA_RCINI_TX1, 0); - SK_OUT8(IoC, B3_MA_RCINI_TX2, 0); - - /* recovery values are needed for XMAC II Rev. B2 only */ - /* Fast Output Enable Mode was intended to use with Rev. B2, but now? */ - - /* - * There is no start or enable button to push, therefore - * the MAC arbiter is configured and enabled now. - */ -} /* SkGeInitMacArb */ - - -/****************************************************************************** - * - * SkGeInitPktArb() - Initialize the Packet Arbiter - * - * Description: - * This function initializes the Packet Arbiter. - * It must not be called if there is still an - * initialized or active port. - * - * Returns: - * nothing - */ -static void SkGeInitPktArb( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_PA_CTRL, PA_RST_CLR); - - /* configure timeout values */ - SK_OUT16(IoC, B3_PA_TOINI_RX1, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_RX2, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_TX1, SK_PKT_TO_MAX); - SK_OUT16(IoC, B3_PA_TOINI_TX2, SK_PKT_TO_MAX); - - /* - * enable timeout timers if jumbo frames not used - * NOTE: the packet arbiter timeout interrupt is needed for - * half duplex hangup workaround - */ - if (pAC->GIni.GIPortUsage != SK_JUMBO_LINK) { - if (pAC->GIni.GIMacsFound == 1) { - SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1); - } - else { - SK_OUT16(IoC, B3_PA_CTRL, PA_ENA_TO_TX1 | PA_ENA_TO_TX2); - } - } -} /* SkGeInitPktArb */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkGeInitMacFifo() - Initialize the MAC FIFOs - * - * Description: - * Initialize all MAC FIFOs of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitMacFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Word; -#ifdef VCPU - SK_U32 DWord; -#endif /* VCPU */ - /* - * For each FIFO: - * - release local reset - * - use default value for MAC FIFO size - * - setup defaults for the control register - * - enable the FIFO - */ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* Configure Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_RX_CTRL_DEF); - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_ENA_OP_MD); - - /* Configure Tx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_ENA_OP_MD); - - /* Enable frame flushing if jumbo frames used */ - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_FLUSH); - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* set Rx GMAC FIFO Flush Mask */ - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_MSK), (SK_U16)RX_FF_FL_DEF_MSK); - - Word = (SK_U16)GMF_RX_CTRL_DEF; - - /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */ - if (pAC->GIni.GIYukonLite && pAC->GIni.GIChipId == CHIP_ID_YUKON) { - - Word &= ~GMF_RX_F_FL_ON; - } - - /* Configure Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), Word); - - /* set Rx GMAC FIFO Flush Threshold (default: 0x0a -> 56 bytes) */ - SK_OUT16(IoC, MR_ADDR(Port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF); - - /* Configure Tx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_CLR); - SK_OUT16(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U16)GMF_TX_CTRL_DEF); - -#ifdef VCPU - SK_IN32(IoC, MR_ADDR(Port, RX_GMF_AF_THR), &DWord); - SK_IN32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), &DWord); -#endif /* VCPU */ - - /* set Tx GMAC FIFO Almost Empty Threshold */ -/* SK_OUT32(IoC, MR_ADDR(Port, TX_GMF_AE_THR), 0); */ - } -#endif /* YUKON */ - -} /* SkGeInitMacFifo */ - -#ifdef SK_LNK_SYNC_CNT -/****************************************************************************** - * - * SkGeLoadLnkSyncCnt() - Load the Link Sync Counter and starts counting - * - * Description: - * This function starts the Link Sync Counter of the specified - * port and enables the generation of an Link Sync IRQ. - * The Link Sync Counter may be used to detect an active link, - * if autonegotiation is not used. - * - * Note: - * o To ensure receiving the Link Sync Event the LinkSyncCounter - * should be initialized BEFORE clearing the XMAC's reset! - * o Enable IS_LNK_SYNC_M1 and IS_LNK_SYNC_M2 after calling this - * function. - * - * Returns: - * nothing - */ -void SkGeLoadLnkSyncCnt( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U32 CntVal) /* Counter value */ -{ - SK_U32 OrgIMsk; - SK_U32 NewIMsk; - SK_U32 ISrc; - SK_BOOL IrqPend; - - /* stop counter */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_STOP); - - /* - * ASIC problem: - * Each time starting the Link Sync Counter an IRQ is generated - * by the adapter. See problem report entry from 21.07.98 - * - * Workaround: Disable Link Sync IRQ and clear the unexpeced IRQ - * if no IRQ is already pending. - */ - IrqPend = SK_FALSE; - SK_IN32(IoC, B0_ISRC, &ISrc); - SK_IN32(IoC, B0_IMSK, &OrgIMsk); - if (Port == MAC_1) { - NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M1; - if ((ISrc & IS_LNK_SYNC_M1) != 0) { - IrqPend = SK_TRUE; - } - } - else { - NewIMsk = OrgIMsk & ~IS_LNK_SYNC_M2; - if ((ISrc & IS_LNK_SYNC_M2) != 0) { - IrqPend = SK_TRUE; - } - } - if (!IrqPend) { - SK_OUT32(IoC, B0_IMSK, NewIMsk); - } - - /* load counter */ - SK_OUT32(IoC, MR_ADDR(Port, LNK_SYNC_INI), CntVal); - - /* start counter */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_START); - - if (!IrqPend) { - /* clear the unexpected IRQ, and restore the interrupt mask */ - SK_OUT8(IoC, MR_ADDR(Port, LNK_SYNC_CTRL), LED_CLR_IRQ); - SK_OUT32(IoC, B0_IMSK, OrgIMsk); - } -} /* SkGeLoadLnkSyncCnt*/ -#endif /* SK_LNK_SYNC_CNT */ - -#if defined(SK_DIAG) || defined(SK_CFG_SYNC) -/****************************************************************************** - * - * SkGeCfgSync() - Configure synchronous bandwidth for this port. - * - * Description: - * This function may be used to configure synchronous bandwidth - * to the specified port. This may be done any time after - * initializing the port. The configuration values are NOT saved - * in the HWAC port structure and will be overwritten any - * time when stopping and starting the port. - * Any values for the synchronous configuration will be ignored - * if the size of the synchronous queue is zero! - * - * The default configuration for the synchronous service is - * TXA_ENA_FSYNC. This means if the size of - * the synchronous queue is unequal zero but no specific - * synchronous bandwidth is configured, the synchronous queue - * will always have the 'unlimited' transmit priority! - * - * This mode will be restored if the synchronous bandwidth is - * deallocated ('IntTime' = 0 and 'LimCount' = 0). - * - * Returns: - * 0: success - * 1: parameter configuration error - * 2: try to configure quality of service although no - * synchronous queue is configured - */ -int SkGeCfgSync( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U32 IntTime, /* Interval Timer Value in units of 8ns */ -SK_U32 LimCount, /* Number of bytes to transfer during IntTime */ -int SyncMode) /* Sync Mode: TXA_ENA_ALLOC | TXA_DIS_ALLOC | 0 */ -{ - int Rtv; - - Rtv = 0; - - /* check the parameters */ - if (LimCount > IntTime || - (LimCount == 0 && IntTime != 0) || - (LimCount != 0 && IntTime == 0)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG); - return(1); - } - - if (pAC->GIni.GP[Port].PXSQSize == 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E009, SKERR_HWI_E009MSG); - return(2); - } - - /* calculate register values */ - IntTime = (IntTime / 2) * pAC->GIni.GIHstClkFact / 100; - LimCount = LimCount / 8; - - if (IntTime > TXA_MAX_VAL || LimCount > TXA_MAX_VAL) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E010, SKERR_HWI_E010MSG); - return(1); - } - - /* - * - Enable 'Force Sync' to ensure the synchronous queue - * has the priority while configuring the new values. - * - Also 'disable alloc' to ensure the settings complies - * to the SyncMode parameter. - * - Disable 'Rate Control' to configure the new values. - * - write IntTime and LimCount - * - start 'Rate Control' and disable 'Force Sync' - * if Interval Timer or Limit Counter not zero. - */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - TXA_ENA_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); - - SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), IntTime); - SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), LimCount); - - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - (SK_U8)(SyncMode & (TXA_ENA_ALLOC | TXA_DIS_ALLOC))); - - if (IntTime != 0 || LimCount != 0) { - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_DIS_FSYNC | TXA_START_RC); - } - - return(0); -} /* SkGeCfgSync */ -#endif /* SK_DIAG || SK_CFG_SYNC*/ - - -/****************************************************************************** - * - * DoInitRamQueue() - Initialize the RAM Buffer Address of a single Queue - * - * Desccription: - * If the queue is used, enable and initialize it. - * Make sure the queue is still reset, if it is not used. - * - * Returns: - * nothing - */ -static void DoInitRamQueue( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int QuIoOffs, /* Queue IO Address Offset */ -SK_U32 QuStartAddr, /* Queue Start Address */ -SK_U32 QuEndAddr, /* Queue End Address */ -int QuType) /* Queue Type (SK_RX_SRAM_Q|SK_RX_BRAM_Q|SK_TX_RAM_Q) */ -{ - SK_U32 RxUpThresVal; - SK_U32 RxLoThresVal; - - if (QuStartAddr != QuEndAddr) { - /* calculate thresholds, assume we have a big Rx queue */ - RxUpThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_ULPP) / 8; - RxLoThresVal = (QuEndAddr + 1 - QuStartAddr - SK_RB_LLPP_B)/8; - - /* build HW address format */ - QuStartAddr = QuStartAddr / 8; - QuEndAddr = QuEndAddr / 8; - - /* release local reset */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_CLR); - - /* configure addresses */ - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_START), QuStartAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_END), QuEndAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_WP), QuStartAddr); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RP), QuStartAddr); - - switch (QuType) { - case SK_RX_SRAM_Q: - /* configure threshold for small Rx Queue */ - RxLoThresVal += (SK_RB_LLPP_B - SK_RB_LLPP_S) / 8; - - /* continue with SK_RX_BRAM_Q */ - case SK_RX_BRAM_Q: - /* write threshold for Rx Queue */ - - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_UTPP), RxUpThresVal); - SK_OUT32(IoC, RB_ADDR(QuIoOffs, RB_RX_LTPP), RxLoThresVal); - - /* the high priority threshold not used */ - break; - case SK_TX_RAM_Q: - /* - * Do NOT use Store & Forward under normal operation due to - * performance optimization (GENESIS only). - * But if Jumbo Frames are configured (XMAC Tx FIFO is only 4 kB) - * or YUKON is used ((GMAC Tx FIFO is only 1 kB) - * we NEED Store & Forward of the RAM buffer. - */ - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK || - pAC->GIni.GIYukon) { - /* enable Store & Forward Mode for the Tx Side */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_STFWD); - } - break; - } - - /* set queue operational */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_ENA_OP_MD); - } - else { - /* ensure the queue is still disabled */ - SK_OUT8(IoC, RB_ADDR(QuIoOffs, RB_CTRL), RB_RST_SET); - } -} /* DoInitRamQueue */ - - -/****************************************************************************** - * - * SkGeInitRamBufs() - Initialize the RAM Buffer Queues - * - * Description: - * Initialize all RAM Buffer Queues of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitRamBufs( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int RxQType; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PRxQSize == SK_MIN_RXQ_SIZE) { - RxQType = SK_RX_SRAM_Q; /* small Rx Queue */ - } - else { - RxQType = SK_RX_BRAM_Q; /* big Rx Queue */ - } - - DoInitRamQueue(pAC, IoC, pPrt->PRxQOff, pPrt->PRxQRamStart, - pPrt->PRxQRamEnd, RxQType); - - DoInitRamQueue(pAC, IoC, pPrt->PXsQOff, pPrt->PXsQRamStart, - pPrt->PXsQRamEnd, SK_TX_RAM_Q); - - DoInitRamQueue(pAC, IoC, pPrt->PXaQOff, pPrt->PXaQRamStart, - pPrt->PXaQRamEnd, SK_TX_RAM_Q); - -} /* SkGeInitRamBufs */ - - -/****************************************************************************** - * - * SkGeInitRamIface() - Initialize the RAM Interface - * - * Description: - * This function initializes the Adapters RAM Interface. - * - * Note: - * This function is used in the diagnostics. - * - * Returns: - * nothing - */ -static void SkGeInitRamIface( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - /* release local reset */ - SK_OUT16(IoC, B3_RI_CTRL, RI_RST_CLR); - - /* configure timeout values */ - SK_OUT8(IoC, B3_RI_WTO_R1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XA1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XS1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_R1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XA1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XS1, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_R2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XA2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_WTO_XS2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_R2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XA2, SK_RI_TO_53); - SK_OUT8(IoC, B3_RI_RTO_XS2, SK_RI_TO_53); - -} /* SkGeInitRamIface */ - - -/****************************************************************************** - * - * SkGeInitBmu() - Initialize the BMU state machines - * - * Description: - * Initialize all BMU state machines of the specified port - * - * Returns: - * nothing - */ -static void SkGeInitBmu( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U32 RxWm; - SK_U32 TxWm; - - pPrt = &pAC->GIni.GP[Port]; - - RxWm = SK_BMU_RX_WM; - TxWm = SK_BMU_TX_WM; - - if (!pAC->GIni.GIPciSlot64 && !pAC->GIni.GIPciClock66) { - /* for better performance */ - RxWm /= 2; - TxWm /= 2; - } - - /* Rx Queue: Release all local resets and set the watermark */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_F), RxWm); - - /* - * Tx Queue: Release all local resets if the queue is used ! - * set watermark - */ - if (pPrt->PXSQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_F), TxWm); - } - - if (pPrt->PXAQSize != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_CLR_RESET); - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_F), TxWm); - } - /* - * Do NOT enable the descriptor poll timers here, because - * the descriptor addresses are not specified yet. - */ -} /* SkGeInitBmu */ - - -/****************************************************************************** - * - * TestStopBit() - Test the stop bit of the queue - * - * Description: - * Stopping a queue is not as simple as it seems to be. - * If descriptor polling is enabled, it may happen - * that RX/TX stop is done and SV idle is NOT set. - * In this case we have to issue another stop command. - * - * Returns: - * The queues control status register - */ -static SK_U32 TestStopBit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int QuIoOffs) /* Queue IO Address Offset */ -{ - SK_U32 QuCsr; /* CSR contents */ - - SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); - - if ((QuCsr & (CSR_STOP | CSR_SV_IDLE)) == 0) { - /* Stop Descriptor overridden by start command */ - SK_OUT32(IoC, Q_ADDR(QuIoOffs, Q_CSR), CSR_STOP); - - SK_IN32(IoC, Q_ADDR(QuIoOffs, Q_CSR), &QuCsr); - } - - return(QuCsr); -} /* TestStopBit */ - - -/****************************************************************************** - * - * SkGeStopPort() - Stop the Rx/Tx activity of the port 'Port'. - * - * Description: - * After calling this function the descriptor rings and Rx and Tx - * queues of this port may be reconfigured. - * - * It is possible to stop the receive and transmit path separate or - * both together. - * - * Dir = SK_STOP_TX Stops the transmit path only and resets the MAC. - * The receive queue is still active and - * the pending Rx frames may be still transferred - * into the RxD. - * SK_STOP_RX Stop the receive path. The tansmit path - * has to be stopped once before. - * SK_STOP_ALL SK_STOP_TX + SK_STOP_RX - * - * RstMode = SK_SOFT_RST Resets the MAC. The PHY is still alive. - * SK_HARD_RST Resets the MAC and the PHY. - * - * Example: - * 1) A Link Down event was signaled for a port. Therefore the activity - * of this port should be stopped and a hardware reset should be issued - * to enable the workaround of XMAC Errata #2. But the received frames - * should not be discarded. - * ... - * SkGeStopPort(pAC, IoC, Port, SK_STOP_TX, SK_HARD_RST); - * (transfer all pending Rx frames) - * SkGeStopPort(pAC, IoC, Port, SK_STOP_RX, SK_HARD_RST); - * ... - * - * 2) An event was issued which request the driver to switch - * the 'virtual active' link to an other already active port - * as soon as possible. The frames in the receive queue of this - * port may be lost. But the PHY must not be reset during this - * event. - * ... - * SkGeStopPort(pAC, IoC, Port, SK_STOP_ALL, SK_SOFT_RST); - * ... - * - * Extended Description: - * If SK_STOP_TX is set, - * o disable the MAC's receive and transmitter to prevent - * from sending incomplete frames - * o stop the port's transmit queues before terminating the - * BMUs to prevent from performing incomplete PCI cycles - * on the PCI bus - * - The network Rx and Tx activity and PCI Tx transfer is - * disabled now. - * o reset the MAC depending on the RstMode - * o Stop Interval Timer and Limit Counter of Tx Arbiter, - * also disable Force Sync bit and Enable Alloc bit. - * o perform a local reset of the port's Tx path - * - reset the PCI FIFO of the async Tx queue - * - reset the PCI FIFO of the sync Tx queue - * - reset the RAM Buffer async Tx queue - * - reset the RAM Buffer sync Tx queue - * - reset the MAC Tx FIFO - * o switch Link and Tx LED off, stop the LED counters - * - * If SK_STOP_RX is set, - * o stop the port's receive queue - * - The path data transfer activity is fully stopped now. - * o perform a local reset of the port's Rx path - * - reset the PCI FIFO of the Rx queue - * - reset the RAM Buffer receive queue - * - reset the MAC Rx FIFO - * o switch Rx LED off, stop the LED counter - * - * If all ports are stopped, - * o reset the RAM Interface. - * - * Notes: - * o This function may be called during the driver states RESET_PORT and - * SWITCH_PORT. - */ -void SkGeStopPort( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* I/O context */ -int Port, /* port to stop (MAC_1 + n) */ -int Dir, /* Direction to Stop (SK_STOP_RX, SK_STOP_TX, SK_STOP_ALL) */ -int RstMode)/* Reset Mode (SK_SOFT_RST, SK_HARD_RST) */ -{ -#ifndef SK_DIAG - SK_EVPARA Para; -#endif /* !SK_DIAG */ - SK_GEPORT *pPrt; - SK_U32 DWord; - SK_U32 XsCsr; - SK_U32 XaCsr; - SK_U64 ToutStart; - int i; - int ToutCnt; - - pPrt = &pAC->GIni.GP[Port]; - - if ((Dir & SK_STOP_TX) != 0) { - /* disable receiver and transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - - /* stop both transmit queues */ - /* - * If the BMU is in the reset state CSR_STOP will terminate - * immediately. - */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_STOP); - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_STOP); - - ToutStart = SkOsGetTime(pAC); - ToutCnt = 0; - do { - /* - * Clear packet arbiter timeout to make sure - * this loop will terminate. - */ - SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ? - PA_CLR_TO_TX1 : PA_CLR_TO_TX2)); - - /* - * If the transfer stucks at the MAC the STOP command will not - * terminate if we don't flush the XMAC's transmit FIFO ! - */ - SkMacFlushTxFifo(pAC, IoC, Port); - - XsCsr = TestStopBit(pAC, IoC, pPrt->PXsQOff); - XaCsr = TestStopBit(pAC, IoC, pPrt->PXaQOff); - - if (SkOsGetTime(pAC) - ToutStart > (SK_TICKS_PER_SEC / 18)) { - /* - * Timeout of 1/18 second reached. - * This needs to be checked at 1/18 sec only. - */ - ToutCnt++; - if (ToutCnt > 1) { - /* Might be a problem when the driver event handler - * calls StopPort again. XXX. - */ - - /* Fatal Error, Loop aborted */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E018, - SKERR_HWI_E018MSG); -#ifndef SK_DIAG - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); -#endif /* !SK_DIAG */ - return; - } - /* - * Cache incoherency workaround: Assume a start command - * has been lost while sending the frame. - */ - ToutStart = SkOsGetTime(pAC); - - if ((XsCsr & CSR_STOP) != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_START); - } - if ((XaCsr & CSR_STOP) != 0) { - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_START); - } - } - - /* - * Because of the ASIC problem report entry from 21.08.1998 it is - * required to wait until CSR_STOP is reset and CSR_SV_IDLE is set. - */ - } while ((XsCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE || - (XaCsr & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); - - /* Reset the MAC depending on the RstMode */ - if (RstMode == SK_SOFT_RST) { - SkMacSoftRst(pAC, IoC, Port); - } - else { - SkMacHardRst(pAC, IoC, Port); - } - - /* Disable Force Sync bit and Enable Alloc bit */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), - TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); - - /* Stop Interval Timer and Limit Counter of Tx Arbiter */ - SK_OUT32(IoC, MR_ADDR(Port, TXA_ITI_INI), 0L); - SK_OUT32(IoC, MR_ADDR(Port, TXA_LIM_INI), 0L); - - /* Perform a local reset of the port's Tx path */ - - /* Reset the PCI FIFO of the async Tx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXaQOff, Q_CSR), CSR_SET_RESET); - /* Reset the PCI FIFO of the sync Tx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PXsQOff, Q_CSR), CSR_SET_RESET); - /* Reset the RAM Buffer async Tx queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PXaQOff, RB_CTRL), RB_RST_SET); - /* Reset the RAM Buffer sync Tx queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PXsQOff, RB_CTRL), RB_RST_SET); - - /* Reset Tx MAC FIFO */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* Note: MFF_RST_SET does NOT reset the XMAC ! */ - SK_OUT8(IoC, MR_ADDR(Port, TX_MFF_CTRL2), MFF_RST_SET); - - /* switch Link and Tx LED off, stop the LED counters */ - /* Link LED is switched off by the RLMT and the Diag itself */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_DIS); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* Reset TX MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); - } -#endif /* YUKON */ - } - - if ((Dir & SK_STOP_RX) != 0) { - /* - * The RX Stop Command will not terminate if no buffers - * are queued in the RxD ring. But it will always reach - * the Idle state. Therefore we can use this feature to - * stop the transfer of received packets. - */ - /* stop the port's receive queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_STOP); - - i = 100; - do { - /* - * Clear packet arbiter timeout to make sure - * this loop will terminate - */ - SK_OUT16(IoC, B3_PA_CTRL, (SK_U16)((Port == MAC_1) ? - PA_CLR_TO_RX1 : PA_CLR_TO_RX2)); - - DWord = TestStopBit(pAC, IoC, pPrt->PRxQOff); - - /* timeout if i==0 (bug fix for #10748) */ - if (--i == 0) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E024, - SKERR_HWI_E024MSG); - break; - } - /* - * because of the ASIC problem report entry from 21.08.98 - * it is required to wait until CSR_STOP is reset and - * CSR_SV_IDLE is set. - */ - } while ((DWord & (CSR_STOP | CSR_SV_IDLE)) != CSR_SV_IDLE); - - /* The path data transfer activity is fully stopped now */ - - /* Perform a local reset of the port's Rx path */ - - /* Reset the PCI FIFO of the Rx queue */ - SK_OUT32(IoC, Q_ADDR(pPrt->PRxQOff, Q_CSR), CSR_SET_RESET); - /* Reset the RAM Buffer receive queue */ - SK_OUT8(IoC, RB_ADDR(pPrt->PRxQOff, RB_CTRL), RB_RST_SET); - - /* Reset Rx MAC FIFO */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SK_OUT8(IoC, MR_ADDR(Port, RX_MFF_CTRL2), MFF_RST_SET); - - /* switch Rx LED off, stop the LED counter */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_DIS); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* Reset Rx MAC FIFO */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_RST_SET); - } -#endif /* YUKON */ - } -} /* SkGeStopPort */ - - -/****************************************************************************** - * - * SkGeInit0() - Level 0 Initialization - * - * Description: - * - Initialize the BMU address offsets - * - * Returns: - * nothing - */ -static void SkGeInit0( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - int i; - SK_GEPORT *pPrt; - - for (i = 0; i < SK_MAX_MACS; i++) { - pPrt = &pAC->GIni.GP[i]; - - pPrt->PState = SK_PRT_RESET; - pPrt->PRxQOff = QOffTab[i].RxQOff; - pPrt->PXsQOff = QOffTab[i].XsQOff; - pPrt->PXaQOff = QOffTab[i].XaQOff; - pPrt->PCheckPar = SK_FALSE; - pPrt->PIsave = 0; - pPrt->PPrevShorts = 0; - pPrt->PLinkResCt = 0; - pPrt->PAutoNegTOCt = 0; - pPrt->PPrevRx = 0; - pPrt->PPrevFcs = 0; - pPrt->PRxLim = SK_DEF_RX_WA_LIM; - pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; - pPrt->PLinkSpeedCap = (SK_U8)SK_LSPEED_CAP_1000MBPS; - pPrt->PLinkSpeed = (SK_U8)SK_LSPEED_1000MBPS; - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_UNKNOWN; - pPrt->PLinkModeConf = (SK_U8)SK_LMODE_AUTOSENSE; - pPrt->PFlowCtrlMode = (SK_U8)SK_FLOW_MODE_SYM_OR_REM; - pPrt->PLinkCap = (SK_U8)(SK_LMODE_CAP_HALF | SK_LMODE_CAP_FULL | - SK_LMODE_CAP_AUTOHALF | SK_LMODE_CAP_AUTOFULL); - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; - pPrt->PFlowCtrlCap = (SK_U8)SK_FLOW_MODE_SYM_OR_REM; - pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; - pPrt->PMSCap = 0; - pPrt->PMSMode = (SK_U8)SK_MS_MODE_AUTO; - pPrt->PMSStatus = (SK_U8)SK_MS_STAT_UNSET; - pPrt->PLipaAutoNeg = (SK_U8)SK_LIPA_UNKNOWN; - pPrt->PAutoNegFail = SK_FALSE; - pPrt->PHWLinkUp = SK_FALSE; - pPrt->PLinkBroken = SK_TRUE; /* See WA code */ - pPrt->PPhyPowerState = PHY_PM_OPERATIONAL_MODE; - pPrt->PMacColThres = TX_COL_DEF; - pPrt->PMacJamLen = TX_JAM_LEN_DEF; - pPrt->PMacJamIpgVal = TX_JAM_IPG_DEF; - pPrt->PMacJamIpgData = TX_IPG_JAM_DEF; - pPrt->PMacIpgData = IPG_DATA_DEF; - pPrt->PMacLimit4 = SK_FALSE; - } - - pAC->GIni.GIPortUsage = SK_RED_LINK; - pAC->GIni.GILedBlinkCtrl = (SK_U16)OemConfig.Value; - pAC->GIni.GIValIrqMask = IS_ALL_MSK; - -} /* SkGeInit0*/ - - -/****************************************************************************** - * - * SkGeInit1() - Level 1 Initialization - * - * Description: - * o Do a software reset. - * o Clear all reset bits. - * o Verify that the detected hardware is present. - * Return an error if not. - * o Get the hardware configuration - * + Read the number of MACs/Ports. - * + Read the RAM size. - * + Read the PCI Revision Id. - * + Find out the adapters host clock speed - * + Read and check the PHY type - * - * Returns: - * 0: success - * 5: Unexpected PHY type detected - * 6: HW self test failed - */ -static int SkGeInit1( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - SK_U8 Byte; - SK_U16 Word; - SK_U16 CtrlStat; - SK_U32 DWord; - int RetVal; - int i; - - RetVal = 0; - - /* save CLK_RUN bits (YUKON-Lite) */ - SK_IN16(IoC, B0_CTST, &CtrlStat); - - /* do the SW-reset */ - SK_OUT8(IoC, B0_CTST, CS_RST_SET); - - /* release the SW-reset */ - SK_OUT8(IoC, B0_CTST, CS_RST_CLR); - - /* reset all error bits in the PCI STATUS register */ - /* - * Note: PCI Cfg cycles cannot be used, because they are not - * available on some platforms after 'boot time'. - */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* release Master Reset */ - SK_OUT8(IoC, B0_CTST, CS_MRST_CLR); - -#ifdef CLK_RUN - CtrlStat |= CS_CLK_RUN_ENA; -#endif /* CLK_RUN */ - - /* restore CLK_RUN bits */ - SK_OUT16(IoC, B0_CTST, (SK_U16)(CtrlStat & - (CS_CLK_RUN_HOT | CS_CLK_RUN_RST | CS_CLK_RUN_ENA))); - - /* read Chip Identification Number */ - SK_IN8(IoC, B2_CHIP_ID, &Byte); - pAC->GIni.GIChipId = Byte; - - /* read number of MACs */ - SK_IN8(IoC, B2_MAC_CFG, &Byte); - pAC->GIni.GIMacsFound = (Byte & CFG_SNG_MAC) ? 1 : 2; - - /* get Chip Revision Number */ - pAC->GIni.GIChipRev = (SK_U8)((Byte & CFG_CHIP_R_MSK) >> 4); - - /* get diff. PCI parameters */ - SK_IN16(IoC, B0_CTST, &CtrlStat); - - /* read the adapters RAM size */ - SK_IN8(IoC, B2_E_0, &Byte); - - pAC->GIni.GIGenesis = SK_FALSE; - pAC->GIni.GIYukon = SK_FALSE; - pAC->GIni.GIYukonLite = SK_FALSE; - -#ifdef GENESIS - if (pAC->GIni.GIChipId == CHIP_ID_GENESIS) { - - pAC->GIni.GIGenesis = SK_TRUE; - - if (Byte == (SK_U8)3) { - /* special case: 4 x 64k x 36, offset = 0x80000 */ - pAC->GIni.GIRamSize = 1024; - pAC->GIni.GIRamOffs = (SK_U32)512 * 1024; - } - else { - pAC->GIni.GIRamSize = (int)Byte * 512; - pAC->GIni.GIRamOffs = 0; - } - /* all GE adapters work with 53.125 MHz host clock */ - pAC->GIni.GIHstClkFact = SK_FACT_53; - - /* set Descr. Poll Timer Init Value to 250 ms */ - pAC->GIni.GIPollTimerVal = - SK_DPOLL_DEF * (SK_U32)pAC->GIni.GIHstClkFact / 100; - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIChipId != CHIP_ID_GENESIS) { - - pAC->GIni.GIYukon = SK_TRUE; - - pAC->GIni.GIRamSize = (Byte == (SK_U8)0) ? 128 : (int)Byte * 4; - - pAC->GIni.GIRamOffs = 0; - - /* WA for chip Rev. A */ - pAC->GIni.GIWolOffs = (pAC->GIni.GIChipId == CHIP_ID_YUKON && - pAC->GIni.GIChipRev == 0) ? WOL_REG_OFFS : 0; - - /* get PM Capabilities of PCI config space */ - SK_IN16(IoC, PCI_C(PCI_PM_CAP_REG), &Word); - - /* check if VAUX is available */ - if (((CtrlStat & CS_VAUX_AVAIL) != 0) && - /* check also if PME from D3cold is set */ - ((Word & PCI_PME_D3C_SUP) != 0)) { - /* set entry in GE init struct */ - pAC->GIni.GIVauxAvail = SK_TRUE; - } - - if (pAC->GIni.GIChipId == CHIP_ID_YUKON_LITE) { - /* this is Rev. A1 */ - pAC->GIni.GIYukonLite = SK_TRUE; - } - else { - /* save Flash-Address Register */ - SK_IN32(IoC, B2_FAR, &DWord); - - /* test Flash-Address Register */ - SK_OUT8(IoC, B2_FAR + 3, 0xff); - SK_IN8(IoC, B2_FAR + 3, &Byte); - - if (Byte != 0) { - /* this is Rev. A0 */ - pAC->GIni.GIYukonLite = SK_TRUE; - - /* restore Flash-Address Register */ - SK_OUT32(IoC, B2_FAR, DWord); - } - } - - /* switch power to VCC (WA for VAUX problem) */ - SK_OUT8(IoC, B0_POWER_CTRL, (SK_U8)(PC_VAUX_ENA | PC_VCC_ENA | - PC_VAUX_OFF | PC_VCC_ON)); - - /* read the Interrupt source */ - SK_IN32(IoC, B0_ISRC, &DWord); - - if ((DWord & IS_HW_ERR) != 0) { - /* read the HW Error Interrupt source */ - SK_IN32(IoC, B0_HWE_ISRC, &DWord); - - if ((DWord & IS_IRQ_SENSOR) != 0) { - /* disable HW Error IRQ */ - pAC->GIni.GIValIrqMask &= ~IS_HW_ERR; - } - } - - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - /* set GMAC Link Control reset */ - SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_SET); - - /* clear GMAC Link Control reset */ - SK_OUT16(IoC, MR_ADDR(i, GMAC_LINK_CTRL), GMLC_RST_CLR); - } - /* all YU chips work with 78.125 MHz host clock */ - pAC->GIni.GIHstClkFact = SK_FACT_78; - - pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; /* 215 ms */ - } -#endif /* YUKON */ - - /* check if 64-bit PCI Slot is present */ - pAC->GIni.GIPciSlot64 = (SK_BOOL)((CtrlStat & CS_BUS_SLOT_SZ) != 0); - - /* check if 66 MHz PCI Clock is active */ - pAC->GIni.GIPciClock66 = (SK_BOOL)((CtrlStat & CS_BUS_CLOCK) != 0); - - /* read PCI HW Revision Id. */ - SK_IN8(IoC, PCI_C(PCI_REV_ID), &Byte); - pAC->GIni.GIPciHwRev = Byte; - - /* read the PMD type */ - SK_IN8(IoC, B2_PMD_TYP, &Byte); - pAC->GIni.GICopperType = (SK_U8)(Byte == 'T'); - - /* read the PHY type */ - SK_IN8(IoC, B2_E_1, &Byte); - - Byte &= 0x0f; /* the PHY type is stored in the lower nibble */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - switch (Byte) { - case SK_PHY_XMAC: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_XMAC; - break; - case SK_PHY_BCOM: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_BCOM; - pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO | - SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_LONE; - break; - case SK_PHY_NAT: - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_NAT; - break; -#endif /* OTHER_PHY */ - default: - /* ERROR: unexpected PHY type detected */ - RetVal = 5; - break; - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - if (Byte < (SK_U8)SK_PHY_MARV_COPPER) { - /* if this field is not initialized */ - Byte = (SK_U8)SK_PHY_MARV_COPPER; - - pAC->GIni.GICopperType = SK_TRUE; - } - - pAC->GIni.GP[i].PhyAddr = PHY_ADDR_MARV; - - if (pAC->GIni.GICopperType) { - - pAC->GIni.GP[i].PLinkSpeedCap = (SK_U8)(SK_LSPEED_CAP_AUTO | - SK_LSPEED_CAP_10MBPS | SK_LSPEED_CAP_100MBPS | - SK_LSPEED_CAP_1000MBPS); - - pAC->GIni.GP[i].PLinkSpeed = (SK_U8)SK_LSPEED_AUTO; - - pAC->GIni.GP[i].PMSCap = (SK_U8)(SK_MS_CAP_AUTO | - SK_MS_CAP_MASTER | SK_MS_CAP_SLAVE); - } - else { - Byte = (SK_U8)SK_PHY_MARV_FIBER; - } - } -#endif /* YUKON */ - - pAC->GIni.GP[i].PhyType = (int)Byte; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("PHY type: %d PHY addr: %04x\n", Byte, - pAC->GIni.GP[i].PhyAddr)); - } - - /* get MAC Type & set function pointers dependent on */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - pAC->GIni.GIMacType = SK_MAC_XMAC; - - pAC->GIni.GIFunc.pFnMacUpdateStats = SkXmUpdateStats; - pAC->GIni.GIFunc.pFnMacStatistic = SkXmMacStatistic; - pAC->GIni.GIFunc.pFnMacResetCounter = SkXmResetCounter; - pAC->GIni.GIFunc.pFnMacOverflow = SkXmOverflowStatus; - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - pAC->GIni.GIMacType = SK_MAC_GMAC; - - pAC->GIni.GIFunc.pFnMacUpdateStats = SkGmUpdateStats; - pAC->GIni.GIFunc.pFnMacStatistic = SkGmMacStatistic; - pAC->GIni.GIFunc.pFnMacResetCounter = SkGmResetCounter; - pAC->GIni.GIFunc.pFnMacOverflow = SkGmOverflowStatus; - -#ifdef SPECIAL_HANDLING - if (pAC->GIni.GIChipId == CHIP_ID_YUKON) { - /* check HW self test result */ - SK_IN8(IoC, B2_E_3, &Byte); - if (Byte & B2_E3_RES_MASK) { - RetVal = 6; - } - } -#endif - } -#endif /* YUKON */ - - return(RetVal); -} /* SkGeInit1 */ - - -/****************************************************************************** - * - * SkGeInit2() - Level 2 Initialization - * - * Description: - * - start the Blink Source Counter - * - start the Descriptor Poll Timer - * - configure the MAC-Arbiter - * - configure the Packet-Arbiter - * - enable the Tx Arbiters - * - enable the RAM Interface Arbiter - * - * Returns: - * nothing - */ -static void SkGeInit2( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ -#ifdef GENESIS - SK_U32 DWord; -#endif /* GENESIS */ - int i; - - /* start the Descriptor Poll Timer */ - if (pAC->GIni.GIPollTimerVal != 0) { - if (pAC->GIni.GIPollTimerVal > SK_DPOLL_MAX) { - pAC->GIni.GIPollTimerVal = SK_DPOLL_MAX; - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E017, SKERR_HWI_E017MSG); - } - SK_OUT32(IoC, B28_DPT_INI, pAC->GIni.GIPollTimerVal); - SK_OUT8(IoC, B28_DPT_CTRL, DPT_START); - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* start the Blink Source Counter */ - DWord = SK_BLK_DUR * (SK_U32)pAC->GIni.GIHstClkFact / 100; - - SK_OUT32(IoC, B2_BSC_INI, DWord); - SK_OUT8(IoC, B2_BSC_CTRL, BSC_START); - - /* - * Configure the MAC Arbiter and the Packet Arbiter. - * They will be started once and never be stopped. - */ - SkGeInitMacArb(pAC, IoC); - - SkGeInitPktArb(pAC, IoC); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* start Time Stamp Timer */ - SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_START); - } -#endif /* YUKON */ - - /* enable the Tx Arbiters */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - SK_OUT8(IoC, MR_ADDR(i, TXA_CTRL), TXA_ENA_ARB); - } - - /* enable the RAM Interface Arbiter */ - SkGeInitRamIface(pAC, IoC); - -} /* SkGeInit2 */ - -/****************************************************************************** - * - * SkGeInit() - Initialize the GE Adapter with the specified level. - * - * Description: - * Level 0: Initialize the Module structures. - * Level 1: Generic Hardware Initialization. The IOP/MemBase pointer has - * to be set before calling this level. - * - * o Do a software reset. - * o Clear all reset bits. - * o Verify that the detected hardware is present. - * Return an error if not. - * o Get the hardware configuration - * + Set GIMacsFound with the number of MACs. - * + Store the RAM size in GIRamSize. - * + Save the PCI Revision ID in GIPciHwRev. - * o return an error - * if Number of MACs > SK_MAX_MACS - * - * After returning from Level 0 the adapter - * may be accessed with IO operations. - * - * Level 2: start the Blink Source Counter - * - * Returns: - * 0: success - * 1: Number of MACs exceeds SK_MAX_MACS (after level 1) - * 2: Adapter not present or not accessible - * 3: Illegal initialization level - * 4: Initialization Level 1 Call missing - * 5: Unexpected PHY type detected - * 6: HW self test failed - */ -int SkGeInit( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Level) /* initialization level */ -{ - int RetVal; /* return value */ - SK_U32 DWord; - - RetVal = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_INIT, - ("SkGeInit(Level %d)\n", Level)); - - switch (Level) { - case SK_INIT_DATA: - /* Initialization Level 0 */ - SkGeInit0(pAC, IoC); - pAC->GIni.GILevel = SK_INIT_DATA; - break; - - case SK_INIT_IO: - /* Initialization Level 1 */ - RetVal = SkGeInit1(pAC, IoC); - if (RetVal != 0) { - break; - } - - /* check if the adapter seems to be accessible */ - SK_OUT32(IoC, B2_IRQM_INI, SK_TEST_VAL); - SK_IN32(IoC, B2_IRQM_INI, &DWord); - SK_OUT32(IoC, B2_IRQM_INI, 0L); - - if (DWord != SK_TEST_VAL) { - RetVal = 2; - break; - } - - /* check if the number of GIMacsFound matches SK_MAX_MACS */ - if (pAC->GIni.GIMacsFound > SK_MAX_MACS) { - RetVal = 1; - break; - } - - /* Level 1 successfully passed */ - pAC->GIni.GILevel = SK_INIT_IO; - break; - - case SK_INIT_RUN: - /* Initialization Level 2 */ - if (pAC->GIni.GILevel != SK_INIT_IO) { -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E002, SKERR_HWI_E002MSG); -#endif /* !SK_DIAG */ - RetVal = 4; - break; - } - SkGeInit2(pAC, IoC); - - /* Level 2 successfully passed */ - pAC->GIni.GILevel = SK_INIT_RUN; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E003, SKERR_HWI_E003MSG); - RetVal = 3; - break; - } - - return(RetVal); -} /* SkGeInit */ - - -/****************************************************************************** - * - * SkGeDeInit() - Deinitialize the adapter - * - * Description: - * All ports of the adapter will be stopped if not already done. - * Do a software reset and switch off all LEDs. - * - * Returns: - * nothing - */ -void SkGeDeInit( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC) /* IO context */ -{ - int i; - SK_U16 Word; - -#if (!defined(SK_SLIM) && !defined(VCPU)) - /* ensure I2C is ready */ - SkI2cWaitIrq(pAC, IoC); -#endif - - /* stop all current transfer activity */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - if (pAC->GIni.GP[i].PState != SK_PRT_STOP && - pAC->GIni.GP[i].PState != SK_PRT_RESET) { - - SkGeStopPort(pAC, IoC, i, SK_STOP_ALL, SK_HARD_RST); - } - } - - /* Reset all bits in the PCI STATUS register */ - /* - * Note: PCI Cfg cycles cannot be used, because they are not - * available on some platforms after 'boot time'. - */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* do the reset, all LEDs are switched off now */ - SK_OUT8(IoC, B0_CTST, CS_RST_SET); - - pAC->GIni.GILevel = SK_INIT_DATA; -} /* SkGeDeInit */ - - -/****************************************************************************** - * - * SkGeInitPort() Initialize the specified port. - * - * Description: - * PRxQSize, PXSQSize, and PXAQSize has to be - * configured for the specified port before calling this function. - * The descriptor rings has to be initialized too. - * - * o (Re)configure queues of the specified port. - * o configure the MAC of the specified port. - * o put ASIC and MAC(s) in operational mode. - * o initialize Rx/Tx and Sync LED - * o initialize RAM Buffers and MAC FIFOs - * - * The port is ready to connect when returning. - * - * Note: - * The MAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * 0: success - * 1: Queue size initialization error. The configured values - * for PRxQSize, PXSQSize, or PXAQSize are invalid for one - * or more queues. The specified port was NOT initialized. - * An error log entry was generated. - * 2: The port has to be stopped before it can be initialized again. - */ -int SkGeInitPort( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port to configure */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (SkGeCheckQSize(pAC, Port) != 0) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E004, SKERR_HWI_E004MSG); - return(1); - } - - if (pPrt->PState == SK_PRT_INIT || pPrt->PState == SK_PRT_RUN) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E005, SKERR_HWI_E005MSG); - return(2); - } - - /* configuration ok, initialize the Port now */ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* initialize Rx, Tx and Link LED */ - /* - * If 1000BT Phy needs LED initialization than swap - * LED and XMAC initialization order - */ - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, TX_LED_INI), SK_LED_ENA); - SkGeXmitLED(pAC, IoC, MR_ADDR(Port, RX_LED_INI), SK_LED_ENA); - /* The Link LED is initialized by RLMT or Diagnostics itself */ - - SkXmInitMac(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmInitMac(pAC, IoC, Port); - } -#endif /* YUKON */ - - /* do NOT initialize the Link Sync Counter */ - - SkGeInitMacFifo(pAC, IoC, Port); - - SkGeInitRamBufs(pAC, IoC, Port); - - if (pPrt->PXSQSize != 0) { - /* enable Force Sync bit if synchronous queue available */ - SK_OUT8(IoC, MR_ADDR(Port, TXA_CTRL), TXA_ENA_FSYNC); - } - - SkGeInitBmu(pAC, IoC, Port); - - /* mark port as initialized */ - pPrt->PState = SK_PRT_INIT; - - return(0); -} /* SkGeInitPort */ diff --git a/drivers/net/sk98lin/skgemib.c b/drivers/net/sk98lin/skgemib.c deleted file mode 100644 index fde45083eb7b..000000000000 --- a/drivers/net/sk98lin/skgemib.c +++ /dev/null @@ -1,1075 +0,0 @@ -/***************************************************************************** - * - * Name: skgemib.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.11 $ - * Date: $Date: 2003/09/15 13:38:12 $ - * Purpose: Private Network Management Interface Management Database - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * PRIVATE OID handler function prototypes - */ -PNMI_STATIC int Addr(SK_AC *pAC, SK_IOC IoC, int action, - SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int CsumStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int General(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Mac8023Stat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int MacPrivateConf(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int MacPrivateStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Monitor(SK_AC *pAC, SK_IOC IoC, int action, - SK_U32 Id, char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int OidStruct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Perform(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int* pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Rlmt(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int RlmtStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int SensorStat(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Vpd(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); - -#ifdef SK_POWER_MGMT -PNMI_STATIC int PowerManagement(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -#endif /* SK_POWER_MGMT */ - -#ifdef SK_DIAG_SUPPORT -PNMI_STATIC int DiagActions(SK_AC *pAC, SK_IOC IoC, int action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, - unsigned int TableIndex, SK_U32 NetIndex); -#endif /* SK_DIAG_SUPPORT */ - - -/* defines *******************************************************************/ -#define ID_TABLE_SIZE ARRAY_SIZE(IdTable) - - -/* global variables **********************************************************/ - -/* - * Table to correlate OID with handler function and index to - * hardware register stored in StatAddress if applicable. - */ -PNMI_STATIC const SK_PNMI_TAB_ENTRY IdTable[] = { - {OID_GEN_XMIT_OK, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX}, - {OID_GEN_RCV_OK, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX}, - {OID_GEN_XMIT_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_RCV_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_RCV_NO_BUFFER, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_GEN_DIRECTED_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNICAST}, - {OID_GEN_MULTICAST_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTICAST}, - {OID_GEN_BROADCAST_FRAMES_XMIT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_BROADCAST}, - {OID_GEN_DIRECTED_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_UNICAST}, - {OID_GEN_MULTICAST_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_MULTICAST}, - {OID_GEN_BROADCAST_FRAMES_RCV, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_BROADCAST}, - {OID_GEN_RCV_CRC_ERROR, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FCS}, - {OID_GEN_TRANSMIT_QUEUE_LENGTH, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_802_3_PERMANENT_ADDRESS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, 0}, - {OID_802_3_CURRENT_ADDRESS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, 0}, - {OID_802_3_RCV_ERROR_ALIGNMENT, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_FRAMING}, - {OID_802_3_XMIT_ONE_COLLISION, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_SINGLE_COL}, - {OID_802_3_XMIT_MORE_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_MULTI_COL}, - {OID_802_3_XMIT_DEFERRED, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_DEFFERAL}, - {OID_802_3_XMIT_MAX_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_EXCESS_COL}, - {OID_802_3_RCV_OVERRUN, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HRX_OVERFLOW}, - {OID_802_3_XMIT_UNDERRUN, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_UNDERRUN}, - {OID_802_3_XMIT_TIMES_CRS_LOST, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_CARRIER}, - {OID_802_3_XMIT_LATE_COLLISIONS, - 0, - 0, - 0, - SK_PNMI_RO, Mac8023Stat, SK_PNMI_HTX_LATE_COL}, -#ifdef SK_POWER_MGMT - {OID_PNP_CAPABILITIES, - 0, - 0, - 0, - SK_PNMI_RO, PowerManagement, 0}, - {OID_PNP_SET_POWER, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_QUERY_POWER, - 0, - 0, - 0, - SK_PNMI_RO, PowerManagement, 0}, - {OID_PNP_ADD_WAKE_UP_PATTERN, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_REMOVE_WAKE_UP_PATTERN, - 0, - 0, - 0, - SK_PNMI_WO, PowerManagement, 0}, - {OID_PNP_ENABLE_WAKE_UP, - 0, - 0, - 0, - SK_PNMI_RW, PowerManagement, 0}, -#endif /* SK_POWER_MGMT */ -#ifdef SK_DIAG_SUPPORT - {OID_SKGE_DIAG_MODE, - 0, - 0, - 0, - SK_PNMI_RW, DiagActions, 0}, -#endif /* SK_DIAG_SUPPORT */ - {OID_SKGE_MDB_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(MgmtDBVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SUPPORTED_LIST, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, - {OID_SKGE_ALL_DATA, - 0, - 0, - 0, - SK_PNMI_RW, OidStruct, 0}, - {OID_SKGE_VPD_FREE_BYTES, - 1, - 0, - SK_PNMI_MAI_OFF(VpdFreeBytes), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ENTRIES_LIST, - 1, - 0, - SK_PNMI_MAI_OFF(VpdEntriesList), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ENTRIES_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(VpdEntriesNumber), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_KEY, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdKey), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_VALUE, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdValue), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ACCESS, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAccess), - SK_PNMI_RO, Vpd, 0}, - {OID_SKGE_VPD_ACTION, - SK_PNMI_VPD_ENTRIES, - sizeof(SK_PNMI_VPD), - SK_PNMI_OFF(Vpd) + SK_PNMI_VPD_OFF(VpdAction), - SK_PNMI_RW, Vpd, 0}, - {OID_SKGE_PORT_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(PortNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DEVICE_TYPE, - 1, - 0, - SK_PNMI_MAI_OFF(DeviceType), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_DESCR, - 1, - 0, - SK_PNMI_MAI_OFF(DriverDescr), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(DriverVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_RELDATE, - 1, - 0, - SK_PNMI_MAI_OFF(DriverReleaseDate), - SK_PNMI_RO, General, 0}, - {OID_SKGE_DRIVER_FILENAME, - 1, - 0, - SK_PNMI_MAI_OFF(DriverFileName), - SK_PNMI_RO, General, 0}, - {OID_SKGE_HW_DESCR, - 1, - 0, - SK_PNMI_MAI_OFF(HwDescr), - SK_PNMI_RO, General, 0}, - {OID_SKGE_HW_VERSION, - 1, - 0, - SK_PNMI_MAI_OFF(HwVersion), - SK_PNMI_RO, General, 0}, - {OID_SKGE_CHIPSET, - 1, - 0, - SK_PNMI_MAI_OFF(Chipset), - SK_PNMI_RO, General, 0}, - {OID_SKGE_CHIPID, - 1, - 0, - SK_PNMI_MAI_OFF(ChipId), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RAMSIZE, - 1, - 0, - SK_PNMI_MAI_OFF(RamSize), - SK_PNMI_RO, General, 0}, - {OID_SKGE_VAUXAVAIL, - 1, - 0, - SK_PNMI_MAI_OFF(VauxAvail), - SK_PNMI_RO, General, 0}, - {OID_SKGE_ACTION, - 1, - 0, - SK_PNMI_MAI_OFF(Action), - SK_PNMI_RW, Perform, 0}, - {OID_SKGE_RESULT, - 1, - 0, - SK_PNMI_MAI_OFF(TestResult), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_TYPE, - 1, - 0, - SK_PNMI_MAI_OFF(BusType), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_SPEED, - 1, - 0, - SK_PNMI_MAI_OFF(BusSpeed), - SK_PNMI_RO, General, 0}, - {OID_SKGE_BUS_WIDTH, - 1, - 0, - SK_PNMI_MAI_OFF(BusWidth), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_SW_QUEUE_LEN, - 1, - 0, - SK_PNMI_MAI_OFF(TxSwQueueLen), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_SW_QUEUE_MAX, - 1, - 0, - SK_PNMI_MAI_OFF(TxSwQueueMax), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_RETRY, - 1, - 0, - SK_PNMI_MAI_OFF(TxRetryCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_INTR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxIntrCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_INTR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxIntrCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_NO_BUF_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxNoBufCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_NO_BUF_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxNoBufCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_USED_DESCR_NO, - 1, - 0, - SK_PNMI_MAI_OFF(TxUsedDescrNo), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_DELIVERED_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxDeliveredCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_OCTETS_DELIV_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxOctetsDeliveredCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RX_HW_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RxHwErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TX_HW_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(TxHwErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_IN_ERRORS_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(InErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_OUT_ERROR_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(OutErrorsCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_ERR_RECOVERY_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(ErrRecoveryCts), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SYSUPTIME, - 1, - 0, - SK_PNMI_MAI_OFF(SysUpTime), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SENSOR_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(SensorNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_SENSOR_INDEX, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorIndex), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_DESCR, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorDescr), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_TYPE, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorType), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_VALUE, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorValue), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_THRES_LOW, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdLow), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_THRES_UPP, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningThresholdHigh), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_THRES_LOW, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdLow), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_THRES_UPP, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorThresholdHigh), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_STATUS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorStatus), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_CTS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningCts), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_CTS, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorCts), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_WAR_TIME, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorWarningTimestamp), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_SENSOR_ERR_TIME, - SK_PNMI_SENSOR_ENTRIES, - sizeof(SK_PNMI_SENSOR), - SK_PNMI_OFF(Sensor) + SK_PNMI_SEN_OFF(SensorErrorTimestamp), - SK_PNMI_RO, SensorStat, 0}, - {OID_SKGE_CHKSM_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(ChecksumNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_CHKSM_RX_OK_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxOkCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_RX_UNABLE_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxUnableCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_RX_ERR_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumRxErrCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_TX_OK_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxOkCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_CHKSM_TX_UNABLE_CTS, - SKCS_NUM_PROTOCOLS, - sizeof(SK_PNMI_CHECKSUM), - SK_PNMI_OFF(Checksum) + SK_PNMI_CHK_OFF(ChecksumTxUnableCts), - SK_PNMI_RO, CsumStat, 0}, - {OID_SKGE_STAT_TX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX}, - {OID_SKGE_STAT_TX_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxOctetsOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_OCTET}, - {OID_SKGE_STAT_TX_BROADCAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBroadcastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BROADCAST}, - {OID_SKGE_STAT_TX_MULTICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMulticastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTICAST}, - {OID_SKGE_STAT_TX_UNICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUnicastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNICAST}, - {OID_SKGE_STAT_TX_LONGFRAMES, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLongFramesCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LONGFRAMES}, - {OID_SKGE_STAT_TX_BURST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxBurstCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_BURST}, - {OID_SKGE_STAT_TX_PFLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxPauseMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_PMACC}, - {OID_SKGE_STAT_TX_FLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MACC}, - {OID_SKGE_STAT_TX_SINGLE_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSingleCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SINGLE_COL}, - {OID_SKGE_STAT_TX_MULTI_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMultipleCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MULTI_COL}, - {OID_SKGE_STAT_TX_EXCESS_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_COL}, - {OID_SKGE_STAT_TX_LATE_COL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxLateCollisionCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_LATE_COL}, - {OID_SKGE_STAT_TX_DEFFERAL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxDeferralCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_DEFFERAL}, - {OID_SKGE_STAT_TX_EXCESS_DEF, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxExcessiveDeferralCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_EXCESS_DEF}, - {OID_SKGE_STAT_TX_UNDERRUN, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxFifoUnderrunCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_UNDERRUN}, - {OID_SKGE_STAT_TX_CARRIER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxCarrierCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_CARRIER}, -/* {OID_SKGE_STAT_TX_UTIL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxUtilization), - SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */ - {OID_SKGE_STAT_TX_64, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx64Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_64}, - {OID_SKGE_STAT_TX_127, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx127Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_127}, - {OID_SKGE_STAT_TX_255, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx255Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_255}, - {OID_SKGE_STAT_TX_511, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx511Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_511}, - {OID_SKGE_STAT_TX_1023, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTx1023Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_1023}, - {OID_SKGE_STAT_TX_MAX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxMaxCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_MAX}, - {OID_SKGE_STAT_TX_SYNC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC}, - {OID_SKGE_STAT_TX_SYNC_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatTxSyncOctetsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HTX_SYNC_OCTET}, - {OID_SKGE_STAT_RX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX}, - {OID_SKGE_STAT_RX_OCTETS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxOctetsOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OCTET}, - {OID_SKGE_STAT_RX_BROADCAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBroadcastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BROADCAST}, - {OID_SKGE_STAT_RX_MULTICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMulticastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MULTICAST}, - {OID_SKGE_STAT_RX_UNICAST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUnicastOkCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_UNICAST}, - {OID_SKGE_STAT_RX_LONGFRAMES, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxLongFramesCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_LONGFRAMES}, - {OID_SKGE_STAT_RX_PFLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC}, - {OID_SKGE_STAT_RX_FLOWC, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC}, - {OID_SKGE_STAT_RX_PFLOWC_ERR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxPauseMacCtrlErrorCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_PMACC_ERR}, - {OID_SKGE_STAT_RX_FLOWC_UNKWN, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMacCtrlUnknownCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MACC_UNKWN}, - {OID_SKGE_STAT_RX_BURST, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxBurstCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_BURST}, - {OID_SKGE_STAT_RX_MISSED, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMissedCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MISSED}, - {OID_SKGE_STAT_RX_FRAMING, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFramingCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FRAMING}, - {OID_SKGE_STAT_RX_OVERFLOW, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFifoOverflowCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_OVERFLOW}, - {OID_SKGE_STAT_RX_JABBER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxJabberCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_JABBER}, - {OID_SKGE_STAT_RX_CARRIER, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCarrierCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CARRIER}, - {OID_SKGE_STAT_RX_IR_LENGTH, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxIRLengthCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_IRLENGTH}, - {OID_SKGE_STAT_RX_SYMBOL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxSymbolCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SYMBOL}, - {OID_SKGE_STAT_RX_SHORTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxShortsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_SHORTS}, - {OID_SKGE_STAT_RX_RUNT, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxRuntCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_RUNT}, - {OID_SKGE_STAT_RX_CEXT, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxCextCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_CEXT}, - {OID_SKGE_STAT_RX_TOO_LONG, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxTooLongCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_TOO_LONG}, - {OID_SKGE_STAT_RX_FCS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxFcsCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_FCS}, -/* {OID_SKGE_STAT_RX_UTIL, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxUtilization), - SK_PNMI_RO, MacPrivateStat, (SK_U16)(-1)}, */ - {OID_SKGE_STAT_RX_64, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx64Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_64}, - {OID_SKGE_STAT_RX_127, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx127Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_127}, - {OID_SKGE_STAT_RX_255, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx255Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_255}, - {OID_SKGE_STAT_RX_511, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx511Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_511}, - {OID_SKGE_STAT_RX_1023, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRx1023Cts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_1023}, - {OID_SKGE_STAT_RX_MAX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_STAT), - SK_PNMI_OFF(Stat) + SK_PNMI_STA_OFF(StatRxMaxCts), - SK_PNMI_RO, MacPrivateStat, SK_PNMI_HRX_MAX}, - {OID_SKGE_PHYS_CUR_ADDR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacCurrentAddr), - SK_PNMI_RW, Addr, 0}, - {OID_SKGE_PHYS_FAC_ADDR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfMacFactoryAddr), - SK_PNMI_RO, Addr, 0}, - {OID_SKGE_PMD, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPMD), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_CONNECTOR, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfConnector), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_PHY_TYPE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyType), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_LINK_MODE_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkModeStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_LINK_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfLinkStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_FLOWCTRL_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfFlowCtrlStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_PHY_OPERATION_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfPhyOperationStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_SPEED_CAP, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedCapability), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_SPEED_MODE, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedMode), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_SPEED_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_CONF), - SK_PNMI_OFF(Conf) + SK_PNMI_CNF_OFF(ConfSpeedStatus), - SK_PNMI_RO, MacPrivateConf, 0}, - {OID_SKGE_TRAP, - 1, - 0, - SK_PNMI_MAI_OFF(Trap), - SK_PNMI_RO, General, 0}, - {OID_SKGE_TRAP_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(TrapNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RLMT_MODE, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtMode), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortNumber), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_ACTIVE, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortActive), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_PREFERRED, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtPortPreferred), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_CTS, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeCts), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_TIME, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeTime), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_ESTIM, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeEstimate), - SK_PNMI_RO, Rlmt, 0}, - {OID_SKGE_RLMT_CHANGE_THRES, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtChangeThreshold), - SK_PNMI_RW, Rlmt, 0}, - {OID_SKGE_RLMT_PORT_INDEX, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtIndex), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_STATUS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtStatus), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_TX_HELLO_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_RX_HELLO_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_TX_SP_REQ_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtTxSpHelloReqCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_RX_SP_CTS, - SK_PNMI_MAC_ENTRIES, - sizeof(SK_PNMI_RLMT), - SK_PNMI_OFF(Rlmt) + SK_PNMI_RLM_OFF(RlmtRxSpHelloCts), - SK_PNMI_RO, RlmtStat, 0}, - {OID_SKGE_RLMT_MONITOR_NUMBER, - 1, - 0, - SK_PNMI_MAI_OFF(RlmtMonitorNumber), - SK_PNMI_RO, General, 0}, - {OID_SKGE_RLMT_MONITOR_INDEX, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorIndex), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ADDR, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAddr), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ERRS, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorErrorCts), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_TIMESTAMP, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorTimestamp), - SK_PNMI_RO, Monitor, 0}, - {OID_SKGE_RLMT_MONITOR_ADMIN, - SK_PNMI_MONITOR_ENTRIES, - sizeof(SK_PNMI_RLMT_MONITOR), - SK_PNMI_OFF(RlmtMonitor) + SK_PNMI_MON_OFF(RlmtMonitorAdmin), - SK_PNMI_RW, Monitor, 0}, - {OID_SKGE_MTU, - 1, - 0, - SK_PNMI_MAI_OFF(MtuSize), - SK_PNMI_RW, MacPrivateConf, 0}, - {OID_SKGE_VCT_GET, - 0, - 0, - 0, - SK_PNMI_RO, Vct, 0}, - {OID_SKGE_VCT_SET, - 0, - 0, - 0, - SK_PNMI_WO, Vct, 0}, - {OID_SKGE_VCT_STATUS, - 0, - 0, - 0, - SK_PNMI_RO, Vct, 0}, - {OID_SKGE_BOARDLEVEL, - 0, - 0, - 0, - SK_PNMI_RO, General, 0}, -}; - diff --git a/drivers/net/sk98lin/skgepnmi.c b/drivers/net/sk98lin/skgepnmi.c deleted file mode 100644 index 876bb2158fa6..000000000000 --- a/drivers/net/sk98lin/skgepnmi.c +++ /dev/null @@ -1,8198 +0,0 @@ -/***************************************************************************** - * - * Name: skgepnmi.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.111 $ - * Date: $Date: 2003/09/15 13:35:35 $ - * Purpose: Private Network Management Interface - * - ****************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - - -#ifndef _lint -static const char SysKonnectFileId[] = - "@(#) $Id: skgepnmi.c,v 1.111 2003/09/15 13:35:35 tschilli Exp $ (C) Marvell."; -#endif /* !_lint */ - -#include "h/skdrv1st.h" -#include "h/sktypes.h" -#include "h/xmac_ii.h" -#include "h/skdebug.h" -#include "h/skqueue.h" -#include "h/skgepnmi.h" -#include "h/skgesirq.h" -#include "h/skcsum.h" -#include "h/skvpd.h" -#include "h/skgehw.h" -#include "h/skgeinit.h" -#include "h/skdrv2nd.h" -#include "h/skgepnm2.h" -#ifdef SK_POWER_MGMT -#include "h/skgepmgt.h" -#endif -/* defines *******************************************************************/ - -#ifndef DEBUG -#define PNMI_STATIC static -#else /* DEBUG */ -#define PNMI_STATIC -#endif /* DEBUG */ - -/* - * Public Function prototypes - */ -int SkPnmiInit(SK_AC *pAC, SK_IOC IoC, int level); -int SkPnmiSetVar(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, void *pBuf, - unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -int SkPnmiGetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiPreSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiSetStruct(SK_AC *pAC, SK_IOC IoC, void *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -int SkPnmiEvent(SK_AC *pAC, SK_IOC IoC, SK_U32 Event, SK_EVPARA Param); -int SkPnmiGenIoctl(SK_AC *pAC, SK_IOC IoC, void * pBuf, - unsigned int * pLen, SK_U32 NetIndex); - - -/* - * Private Function prototypes - */ - -PNMI_STATIC SK_U8 CalculateLinkModeStatus(SK_AC *pAC, SK_IOC IoC, unsigned int - PhysPortIndex); -PNMI_STATIC SK_U8 CalculateLinkStatus(SK_AC *pAC, SK_IOC IoC, unsigned int - PhysPortIndex); -PNMI_STATIC void CopyMac(char *pDst, SK_MAC_ADDR *pMac); -PNMI_STATIC void CopyTrapQueue(SK_AC *pAC, char *pDstBuf); -PNMI_STATIC SK_U64 GetPhysStatVal(SK_AC *pAC, SK_IOC IoC, - unsigned int PhysPortIndex, unsigned int StatIndex); -PNMI_STATIC SK_U64 GetStatVal(SK_AC *pAC, SK_IOC IoC, unsigned int LogPortIndex, - unsigned int StatIndex, SK_U32 NetIndex); -PNMI_STATIC char* GetTrapEntry(SK_AC *pAC, SK_U32 TrapId, unsigned int Size); -PNMI_STATIC void GetTrapQueueLen(SK_AC *pAC, unsigned int *pLen, - unsigned int *pEntries); -PNMI_STATIC int GetVpdKeyArr(SK_AC *pAC, SK_IOC IoC, char *pKeyArr, - unsigned int KeyArrLen, unsigned int *pKeyNo); -PNMI_STATIC int LookupId(SK_U32 Id); -PNMI_STATIC int MacUpdate(SK_AC *pAC, SK_IOC IoC, unsigned int FirstMac, - unsigned int LastMac); -PNMI_STATIC int PnmiStruct(SK_AC *pAC, SK_IOC IoC, int Action, char *pBuf, - unsigned int *pLen, SK_U32 NetIndex); -PNMI_STATIC int PnmiVar(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, - char *pBuf, unsigned int *pLen, SK_U32 Instance, SK_U32 NetIndex); -PNMI_STATIC void QueueRlmtNewMacTrap(SK_AC *pAC, unsigned int ActiveMac); -PNMI_STATIC void QueueRlmtPortTrap(SK_AC *pAC, SK_U32 TrapId, - unsigned int PortIndex); -PNMI_STATIC void QueueSensorTrap(SK_AC *pAC, SK_U32 TrapId, - unsigned int SensorIndex); -PNMI_STATIC void QueueSimpleTrap(SK_AC *pAC, SK_U32 TrapId); -PNMI_STATIC void ResetCounter(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); -PNMI_STATIC int RlmtUpdate(SK_AC *pAC, SK_IOC IoC, SK_U32 NetIndex); -PNMI_STATIC int SirqUpdate(SK_AC *pAC, SK_IOC IoC); -PNMI_STATIC void VirtualConf(SK_AC *pAC, SK_IOC IoC, SK_U32 Id, char *pBuf); -PNMI_STATIC int Vct(SK_AC *pAC, SK_IOC IoC, int Action, SK_U32 Id, char *pBuf, - unsigned int *pLen, SK_U32 Instance, unsigned int TableIndex, SK_U32 NetIndex); -PNMI_STATIC void CheckVctStatus(SK_AC *, SK_IOC, char *, SK_U32, SK_U32); - -/* - * Table to correlate OID with handler function and index to - * hardware register stored in StatAddress if applicable. - */ -#include "skgemib.c" - -/* global variables **********************************************************/ - -/* - * Overflow status register bit table and corresponding counter - * dependent on MAC type - the number relates to the size of overflow - * mask returned by the pFnMacOverflow function - */ -PNMI_STATIC const SK_U16 StatOvrflwBit[][SK_PNMI_MAC_TYPES] = { -/* Bit0 */ { SK_PNMI_HTX, SK_PNMI_HTX_UNICAST}, -/* Bit1 */ { SK_PNMI_HTX_OCTETHIGH, SK_PNMI_HTX_BROADCAST}, -/* Bit2 */ { SK_PNMI_HTX_OCTETLOW, SK_PNMI_HTX_PMACC}, -/* Bit3 */ { SK_PNMI_HTX_BROADCAST, SK_PNMI_HTX_MULTICAST}, -/* Bit4 */ { SK_PNMI_HTX_MULTICAST, SK_PNMI_HTX_OCTETLOW}, -/* Bit5 */ { SK_PNMI_HTX_UNICAST, SK_PNMI_HTX_OCTETHIGH}, -/* Bit6 */ { SK_PNMI_HTX_LONGFRAMES, SK_PNMI_HTX_64}, -/* Bit7 */ { SK_PNMI_HTX_BURST, SK_PNMI_HTX_127}, -/* Bit8 */ { SK_PNMI_HTX_PMACC, SK_PNMI_HTX_255}, -/* Bit9 */ { SK_PNMI_HTX_MACC, SK_PNMI_HTX_511}, -/* Bit10 */ { SK_PNMI_HTX_SINGLE_COL, SK_PNMI_HTX_1023}, -/* Bit11 */ { SK_PNMI_HTX_MULTI_COL, SK_PNMI_HTX_MAX}, -/* Bit12 */ { SK_PNMI_HTX_EXCESS_COL, SK_PNMI_HTX_LONGFRAMES}, -/* Bit13 */ { SK_PNMI_HTX_LATE_COL, SK_PNMI_HTX_RESERVED}, -/* Bit14 */ { SK_PNMI_HTX_DEFFERAL, SK_PNMI_HTX_COL}, -/* Bit15 */ { SK_PNMI_HTX_EXCESS_DEF, SK_PNMI_HTX_LATE_COL}, -/* Bit16 */ { SK_PNMI_HTX_UNDERRUN, SK_PNMI_HTX_EXCESS_COL}, -/* Bit17 */ { SK_PNMI_HTX_CARRIER, SK_PNMI_HTX_MULTI_COL}, -/* Bit18 */ { SK_PNMI_HTX_UTILUNDER, SK_PNMI_HTX_SINGLE_COL}, -/* Bit19 */ { SK_PNMI_HTX_UTILOVER, SK_PNMI_HTX_UNDERRUN}, -/* Bit20 */ { SK_PNMI_HTX_64, SK_PNMI_HTX_RESERVED}, -/* Bit21 */ { SK_PNMI_HTX_127, SK_PNMI_HTX_RESERVED}, -/* Bit22 */ { SK_PNMI_HTX_255, SK_PNMI_HTX_RESERVED}, -/* Bit23 */ { SK_PNMI_HTX_511, SK_PNMI_HTX_RESERVED}, -/* Bit24 */ { SK_PNMI_HTX_1023, SK_PNMI_HTX_RESERVED}, -/* Bit25 */ { SK_PNMI_HTX_MAX, SK_PNMI_HTX_RESERVED}, -/* Bit26 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit27 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit28 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit29 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit30 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit31 */ { SK_PNMI_HTX_RESERVED, SK_PNMI_HTX_RESERVED}, -/* Bit32 */ { SK_PNMI_HRX, SK_PNMI_HRX_UNICAST}, -/* Bit33 */ { SK_PNMI_HRX_OCTETHIGH, SK_PNMI_HRX_BROADCAST}, -/* Bit34 */ { SK_PNMI_HRX_OCTETLOW, SK_PNMI_HRX_PMACC}, -/* Bit35 */ { SK_PNMI_HRX_BROADCAST, SK_PNMI_HRX_MULTICAST}, -/* Bit36 */ { SK_PNMI_HRX_MULTICAST, SK_PNMI_HRX_FCS}, -/* Bit37 */ { SK_PNMI_HRX_UNICAST, SK_PNMI_HRX_RESERVED}, -/* Bit38 */ { SK_PNMI_HRX_PMACC, SK_PNMI_HRX_OCTETLOW}, -/* Bit39 */ { SK_PNMI_HRX_MACC, SK_PNMI_HRX_OCTETHIGH}, -/* Bit40 */ { SK_PNMI_HRX_PMACC_ERR, SK_PNMI_HRX_BADOCTETLOW}, -/* Bit41 */ { SK_PNMI_HRX_MACC_UNKWN, SK_PNMI_HRX_BADOCTETHIGH}, -/* Bit42 */ { SK_PNMI_HRX_BURST, SK_PNMI_HRX_UNDERSIZE}, -/* Bit43 */ { SK_PNMI_HRX_MISSED, SK_PNMI_HRX_RUNT}, -/* Bit44 */ { SK_PNMI_HRX_FRAMING, SK_PNMI_HRX_64}, -/* Bit45 */ { SK_PNMI_HRX_OVERFLOW, SK_PNMI_HRX_127}, -/* Bit46 */ { SK_PNMI_HRX_JABBER, SK_PNMI_HRX_255}, -/* Bit47 */ { SK_PNMI_HRX_CARRIER, SK_PNMI_HRX_511}, -/* Bit48 */ { SK_PNMI_HRX_IRLENGTH, SK_PNMI_HRX_1023}, -/* Bit49 */ { SK_PNMI_HRX_SYMBOL, SK_PNMI_HRX_MAX}, -/* Bit50 */ { SK_PNMI_HRX_SHORTS, SK_PNMI_HRX_LONGFRAMES}, -/* Bit51 */ { SK_PNMI_HRX_RUNT, SK_PNMI_HRX_TOO_LONG}, -/* Bit52 */ { SK_PNMI_HRX_TOO_LONG, SK_PNMI_HRX_JABBER}, -/* Bit53 */ { SK_PNMI_HRX_FCS, SK_PNMI_HRX_RESERVED}, -/* Bit54 */ { SK_PNMI_HRX_RESERVED, SK_PNMI_HRX_OVERFLOW}, -/* Bit55 */ { SK_PNMI_HRX_CEXT, SK_PNMI_HRX_RESERVED}, -/* Bit56 */ { SK_PNMI_HRX_UTILUNDER, SK_PNMI_HRX_RESERVED}, -/* Bit57 */ { SK_PNMI_HRX_UTILOVER, SK_PNMI_HRX_RESERVED}, -/* Bit58 */ { SK_PNMI_HRX_64, SK_PNMI_HRX_RESERVED}, -/* Bit59 */ { SK_PNMI_HRX_127, SK_PNMI_HRX_RESERVED}, -/* Bit60 */ { SK_PNMI_HRX_255, SK_PNMI_HRX_RESERVED}, -/* Bit61 */ { SK_PNMI_HRX_511, SK_PNMI_HRX_RESERVED}, -/* Bit62 */ { SK_PNMI_HRX_1023, SK_PNMI_HRX_RESERVED}, -/* Bit63 */ { SK_PNMI_HRX_MAX, SK_PNMI_HRX_RESERVED} -}; - -/* - * Table for hardware register saving on resets and port switches - */ -PNMI_STATIC const SK_PNMI_STATADDR StatAddr[SK_PNMI_MAX_IDX][SK_PNMI_MAC_TYPES] = { - /* SK_PNMI_HTX */ - {{XM_TXF_OK, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_OCTETHIGH */ - {{XM_TXO_OK_HI, SK_TRUE}, {GM_TXO_OK_HI, SK_TRUE}}, - /* SK_PNMI_HTX_OCTETLOW */ - {{XM_TXO_OK_LO, SK_FALSE}, {GM_TXO_OK_LO, SK_FALSE}}, - /* SK_PNMI_HTX_BROADCAST */ - {{XM_TXF_BC_OK, SK_TRUE}, {GM_TXF_BC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_MULTICAST */ - {{XM_TXF_MC_OK, SK_TRUE}, {GM_TXF_MC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_UNICAST */ - {{XM_TXF_UC_OK, SK_TRUE}, {GM_TXF_UC_OK, SK_TRUE}}, - /* SK_PNMI_HTX_BURST */ - {{XM_TXE_BURST, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_PMACC */ - {{XM_TXF_MPAUSE, SK_TRUE}, {GM_TXF_MPAUSE, SK_TRUE}}, - /* SK_PNMI_HTX_MACC */ - {{XM_TXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_COL */ - {{0, SK_FALSE}, {GM_TXF_COL, SK_TRUE}}, - /* SK_PNMI_HTX_SINGLE_COL */ - {{XM_TXF_SNG_COL, SK_TRUE}, {GM_TXF_SNG_COL, SK_TRUE}}, - /* SK_PNMI_HTX_MULTI_COL */ - {{XM_TXF_MUL_COL, SK_TRUE}, {GM_TXF_MUL_COL, SK_TRUE}}, - /* SK_PNMI_HTX_EXCESS_COL */ - {{XM_TXF_ABO_COL, SK_TRUE}, {GM_TXF_ABO_COL, SK_TRUE}}, - /* SK_PNMI_HTX_LATE_COL */ - {{XM_TXF_LAT_COL, SK_TRUE}, {GM_TXF_LAT_COL, SK_TRUE}}, - /* SK_PNMI_HTX_DEFFERAL */ - {{XM_TXF_DEF, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_EXCESS_DEF */ - {{XM_TXF_EX_DEF, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UNDERRUN */ - {{XM_TXE_FIFO_UR, SK_TRUE}, {GM_TXE_FIFO_UR, SK_TRUE}}, - /* SK_PNMI_HTX_CARRIER */ - {{XM_TXE_CS_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UTILUNDER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_UTILOVER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_64 */ - {{XM_TXF_64B, SK_TRUE}, {GM_TXF_64B, SK_TRUE}}, - /* SK_PNMI_HTX_127 */ - {{XM_TXF_127B, SK_TRUE}, {GM_TXF_127B, SK_TRUE}}, - /* SK_PNMI_HTX_255 */ - {{XM_TXF_255B, SK_TRUE}, {GM_TXF_255B, SK_TRUE}}, - /* SK_PNMI_HTX_511 */ - {{XM_TXF_511B, SK_TRUE}, {GM_TXF_511B, SK_TRUE}}, - /* SK_PNMI_HTX_1023 */ - {{XM_TXF_1023B, SK_TRUE}, {GM_TXF_1023B, SK_TRUE}}, - /* SK_PNMI_HTX_MAX */ - {{XM_TXF_MAX_SZ, SK_TRUE}, {GM_TXF_1518B, SK_TRUE}}, - /* SK_PNMI_HTX_LONGFRAMES */ - {{XM_TXF_LONG, SK_TRUE}, {GM_TXF_MAX_SZ, SK_TRUE}}, - /* SK_PNMI_HTX_SYNC */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_SYNC_OCTET */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HTX_RESERVED */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX */ - {{XM_RXF_OK, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_OCTETHIGH */ - {{XM_RXO_OK_HI, SK_TRUE}, {GM_RXO_OK_HI, SK_TRUE}}, - /* SK_PNMI_HRX_OCTETLOW */ - {{XM_RXO_OK_LO, SK_FALSE}, {GM_RXO_OK_LO, SK_FALSE}}, - /* SK_PNMI_HRX_BADOCTETHIGH */ - {{0, SK_FALSE}, {GM_RXO_ERR_HI, SK_TRUE}}, - /* SK_PNMI_HRX_BADOCTETLOW */ - {{0, SK_FALSE}, {GM_RXO_ERR_LO, SK_TRUE}}, - /* SK_PNMI_HRX_BROADCAST */ - {{XM_RXF_BC_OK, SK_TRUE}, {GM_RXF_BC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_MULTICAST */ - {{XM_RXF_MC_OK, SK_TRUE}, {GM_RXF_MC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_UNICAST */ - {{XM_RXF_UC_OK, SK_TRUE}, {GM_RXF_UC_OK, SK_TRUE}}, - /* SK_PNMI_HRX_PMACC */ - {{XM_RXF_MPAUSE, SK_TRUE}, {GM_RXF_MPAUSE, SK_TRUE}}, - /* SK_PNMI_HRX_MACC */ - {{XM_RXF_MCTRL, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_PMACC_ERR */ - {{XM_RXF_INV_MP, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_MACC_UNKWN */ - {{XM_RXF_INV_MOC, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_BURST */ - {{XM_RXE_BURST, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_MISSED */ - {{XM_RXE_FMISS, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_FRAMING */ - {{XM_RXF_FRA_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UNDERSIZE */ - {{0, SK_FALSE}, {GM_RXF_SHT, SK_TRUE}}, - /* SK_PNMI_HRX_OVERFLOW */ - {{XM_RXE_FIFO_OV, SK_TRUE}, {GM_RXE_FIFO_OV, SK_TRUE}}, - /* SK_PNMI_HRX_JABBER */ - {{XM_RXF_JAB_PKT, SK_TRUE}, {GM_RXF_JAB_PKT, SK_TRUE}}, - /* SK_PNMI_HRX_CARRIER */ - {{XM_RXE_CAR_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_IRLENGTH */ - {{XM_RXF_LEN_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_SYMBOL */ - {{XM_RXE_SYM_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_SHORTS */ - {{XM_RXE_SHT_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_RUNT */ - {{XM_RXE_RUNT, SK_TRUE}, {GM_RXE_FRAG, SK_TRUE}}, - /* SK_PNMI_HRX_TOO_LONG */ - {{XM_RXF_LNG_ERR, SK_TRUE}, {GM_RXF_LNG_ERR, SK_TRUE}}, - /* SK_PNMI_HRX_FCS */ - {{XM_RXF_FCS_ERR, SK_TRUE}, {GM_RXF_FCS_ERR, SK_TRUE}}, - /* SK_PNMI_HRX_CEXT */ - {{XM_RXF_CEX_ERR, SK_TRUE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UTILUNDER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_UTILOVER */ - {{0, SK_FALSE}, {0, SK_FALSE}}, - /* SK_PNMI_HRX_64 */ - {{XM_RXF_64B, SK_TRUE}, {GM_RXF_64B, SK_TRUE}}, - /* SK_PNMI_HRX_127 */ - {{XM_RXF_127B, SK_TRUE}, {GM_RXF_127B, SK_TRUE}}, - /* SK_PNMI_HRX_255 */ - {{XM_RXF_255B, SK_TRUE}, {GM_RXF_255B, SK_TRUE}}, - /* SK_PNMI_HRX_511 */ - {{XM_RXF_511B, SK_TRUE}, {GM_RXF_511B, SK_TRUE}}, - /* SK_PNMI_HRX_1023 */ - {{XM_RXF_1023B, SK_TRUE}, {GM_RXF_1023B, SK_TRUE}}, - /* SK_PNMI_HRX_MAX */ - {{XM_RXF_MAX_SZ, SK_TRUE}, {GM_RXF_1518B, SK_TRUE}}, - /* SK_PNMI_HRX_LONGFRAMES */ - {{0, SK_FALSE}, {GM_RXF_MAX_SZ, SK_TRUE}}, - /* SK_PNMI_HRX_RESERVED */ - {{0, SK_FALSE}, {0, SK_FALSE}} -}; - - -/***************************************************************************** - * - * Public functions - * - */ - -/***************************************************************************** - * - * SkPnmiInit - Init function of PNMI - * - * Description: - * SK_INIT_DATA: Initialises the data structures - * SK_INIT_IO: Resets the XMAC statistics, determines the device and - * connector type. - * SK_INIT_RUN: Starts a timer event for port switch per hour - * calculation. - * - * Returns: - * Always 0 - */ -int SkPnmiInit( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Level) /* Initialization level */ -{ - unsigned int PortMax; /* Number of ports */ - unsigned int PortIndex; /* Current port index in loop */ - SK_U16 Val16; /* Multiple purpose 16 bit variable */ - SK_U8 Val8; /* Mulitple purpose 8 bit variable */ - SK_EVPARA EventParam; /* Event struct for timer event */ - SK_PNMI_VCT *pVctBackupData; - - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiInit: Called, level=%d\n", Level)); - - switch (Level) { - - case SK_INIT_DATA: - SK_MEMSET((char *)&pAC->Pnmi, 0, sizeof(pAC->Pnmi)); - pAC->Pnmi.TrapBufFree = SK_PNMI_TRAP_QUEUE_LEN; - pAC->Pnmi.StartUpTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - pAC->Pnmi.RlmtChangeThreshold = SK_PNMI_DEF_RLMT_CHG_THRES; - for (PortIndex = 0; PortIndex < SK_MAX_MACS; PortIndex ++) { - - pAC->Pnmi.Port[PortIndex].ActiveFlag = SK_FALSE; - pAC->Pnmi.DualNetActiveFlag = SK_FALSE; - } - -#ifdef SK_PNMI_CHECK - if (SK_PNMI_MAX_IDX != SK_PNMI_CNT_NO) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR049, SK_PNMI_ERR049MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_INIT | SK_DBGCAT_FATAL, - ("CounterOffset struct size (%d) differs from " - "SK_PNMI_MAX_IDX (%d)\n", - SK_PNMI_CNT_NO, SK_PNMI_MAX_IDX)); - } - -#endif /* SK_PNMI_CHECK */ - break; - - case SK_INIT_IO: - /* - * Reset MAC counters - */ - PortMax = pAC->GIni.GIMacsFound; - - for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { - - pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PortIndex); - } - - /* Initialize DSP variables for Vct() to 0xff => Never written! */ - for (PortIndex = 0; PortIndex < PortMax; PortIndex ++) { - pAC->GIni.GP[PortIndex].PCableLen = 0xff; - pVctBackupData = &pAC->Pnmi.VctBackup[PortIndex]; - pVctBackupData->PCableLen = 0xff; - } - - /* - * Get pci bus speed - */ - SK_IN16(IoC, B0_CTST, &Val16); - if ((Val16 & CS_BUS_CLOCK) == 0) { - - pAC->Pnmi.PciBusSpeed = 33; - } - else { - pAC->Pnmi.PciBusSpeed = 66; - } - - /* - * Get pci bus width - */ - SK_IN16(IoC, B0_CTST, &Val16); - if ((Val16 & CS_BUS_SLOT_SZ) == 0) { - - pAC->Pnmi.PciBusWidth = 32; - } - else { - pAC->Pnmi.PciBusWidth = 64; - } - - /* - * Get chipset - */ - switch (pAC->GIni.GIChipId) { - case CHIP_ID_GENESIS: - pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_XMAC; - break; - - case CHIP_ID_YUKON: - pAC->Pnmi.Chipset = SK_PNMI_CHIPSET_YUKON; - break; - - default: - break; - } - - /* - * Get PMD and DeviceType - */ - SK_IN8(IoC, B2_PMD_TYP, &Val8); - switch (Val8) { - case 'S': - pAC->Pnmi.PMD = 3; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020002; - } - else { - pAC->Pnmi.DeviceType = 0x00020001; - } - break; - - case 'L': - pAC->Pnmi.PMD = 2; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020004; - } - else { - pAC->Pnmi.DeviceType = 0x00020003; - } - break; - - case 'C': - pAC->Pnmi.PMD = 4; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020006; - } - else { - pAC->Pnmi.DeviceType = 0x00020005; - } - break; - - case 'T': - pAC->Pnmi.PMD = 5; - if (pAC->GIni.GIMacsFound > 1) { - - pAC->Pnmi.DeviceType = 0x00020008; - } - else { - pAC->Pnmi.DeviceType = 0x00020007; - } - break; - - default : - pAC->Pnmi.PMD = 1; - pAC->Pnmi.DeviceType = 0; - break; - } - - /* - * Get connector - */ - SK_IN8(IoC, B2_CONN_TYP, &Val8); - switch (Val8) { - case 'C': - pAC->Pnmi.Connector = 2; - break; - - case 'D': - pAC->Pnmi.Connector = 3; - break; - - case 'F': - pAC->Pnmi.Connector = 4; - break; - - case 'J': - pAC->Pnmi.Connector = 5; - break; - - case 'V': - pAC->Pnmi.Connector = 6; - break; - - default: - pAC->Pnmi.Connector = 1; - break; - } - break; - - case SK_INIT_RUN: - /* - * Start timer for RLMT change counter - */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, - 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, - EventParam); - break; - - default: - break; /* Nothing todo */ - } - - return (0); -} - -/***************************************************************************** - * - * SkPnmiGetVar - Retrieves the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. If the instance - * -1 is passed, the values of all instances are returned in an - * array of values. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed - * SK_PNMI_ERR_GENERAL A general severe internal error occured - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take - * the data. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -static int SkPnmiGetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer to which the management data will be copied */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiGetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - return (PnmiVar(pAC, IoC, SK_PNMI_GET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiPreSetVar - Presets the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is useful to check if a set might be successfull. - * If the instance -1 is passed, an array of values is supposed and - * all instances of the OID will be set. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -static int SkPnmiPreSetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer to which the management data will be copied */ -unsigned int *pLen, /* Total length of management data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiPreSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - - return (PnmiVar(pAC, IoC, SK_PNMI_PRESET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiSetVar - Sets the value of a single OID - * - * Description: - * Calls a general sub-function for all this stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is useful to check if a set might be successfull. - * If the instance -1 is passed, an array of values is supposed and - * all instances of the OID will be set. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -int SkPnmiSetVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -void *pBuf, /* Buffer to which the management data will be copied */ -unsigned int *pLen, /* Total length of management data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiSetVar: Called, Id=0x%x, BufLen=%d, Instance=%d, NetIndex=%d\n", - Id, *pLen, Instance, NetIndex)); - - return (PnmiVar(pAC, IoC, SK_PNMI_SET, Id, (char *)pBuf, pLen, - Instance, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiGetStruct - Retrieves the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Runs through the IdTable, queries the single OIDs and stores the - * returned data into the management database structure - * SK_PNMI_STRUCT_DATA. The offset of the OID in the structure - * is stored in the IdTable. The return value of the function will also - * be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the - * minimum size of SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed - * SK_PNMI_ERR_GENERAL A general severe internal error occured - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take - * the data. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -int SkPnmiGetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer to which the management data will be copied. */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int TableIndex; - unsigned int DstOffset; - unsigned int InstanceNo; - unsigned int InstanceCnt; - SK_U32 Instance; - unsigned int TmpLen; - char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; - - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiGetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - if (*pLen < SK_PNMI_STRUCT_SIZE) { - - if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { - - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, - (SK_U32)(-1)); - } - - *pLen = SK_PNMI_STRUCT_SIZE; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Check NetIndex - */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - /* Update statistic */ - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On call"); - - if ((Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1)) != - SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - /* - * Increment semaphores to indicate that an update was - * already done - */ - pAC->Pnmi.MacUpdatedFlag ++; - pAC->Pnmi.RlmtUpdatedFlag ++; - pAC->Pnmi.SirqUpdatedFlag ++; - - /* Get vpd keys for instance calculation */ - Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &TmpLen); - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_GENERAL); - } - - /* Retrieve values */ - SK_MEMSET((char *)pBuf, 0, SK_PNMI_STRUCT_SIZE); - for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { - - InstanceNo = IdTable[TableIndex].InstanceNo; - for (InstanceCnt = 1; InstanceCnt <= InstanceNo; - InstanceCnt ++) { - - DstOffset = IdTable[TableIndex].Offset + - (InstanceCnt - 1) * - IdTable[TableIndex].StructSize; - - /* - * For the VPD the instance is not an index number - * but the key itself. Determin with the instance - * counter the VPD key to be used. - */ - if (IdTable[TableIndex].Id == OID_SKGE_VPD_KEY || - IdTable[TableIndex].Id == OID_SKGE_VPD_VALUE || - IdTable[TableIndex].Id == OID_SKGE_VPD_ACCESS || - IdTable[TableIndex].Id == OID_SKGE_VPD_ACTION) { - - SK_STRNCPY((char *)&Instance, KeyArr[InstanceCnt - 1], 4); - } - else { - Instance = (SK_U32)InstanceCnt; - } - - TmpLen = *pLen - DstOffset; - Ret = IdTable[TableIndex].Func(pAC, IoC, SK_PNMI_GET, - IdTable[TableIndex].Id, (char *)pBuf + - DstOffset, &TmpLen, Instance, TableIndex, NetIndex); - - /* - * An unknown instance error means that we reached - * the last instance of that variable. Proceed with - * the next OID in the table and ignore the return - * code. - */ - if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { - - break; - } - - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, Ret, DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - } - } - - pAC->Pnmi.MacUpdatedFlag --; - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - *pLen = SK_PNMI_STRUCT_SIZE; - SK_PNMI_CHECKFLAGS("SkPnmiGetStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SkPnmiPreSetStruct - Presets the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Calls a general sub-function for all this set stuff. The preset does - * the same as a set, but returns just before finally setting the - * new value. This is useful to check if a set might be successfull. - * The sub-function runs through the IdTable, checks which OIDs are able - * to set, and calls the handler function of the OID to perform the - * preset. The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - */ -int SkPnmiPreSetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer which contains the data to be set */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiPreSetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - return (PnmiStruct(pAC, IoC, SK_PNMI_PRESET, (char *)pBuf, - pLen, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiSetStruct - Sets the management database in SK_PNMI_STRUCT_DATA - * - * Description: - * Calls a general sub-function for all this set stuff. The return value - * of the function will also be stored in SK_PNMI_STRUCT_DATA if the - * passed buffer has the minimum size of SK_PNMI_MIN_STRUCT_SIZE. - * The sub-function runs through the IdTable, checks which OIDs are able - * to set, and calls the handler function of the OID to perform the - * set. The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - */ -int SkPnmiSetStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -void *pBuf, /* Buffer which contains the data to be set */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiSetStruct: Called, BufLen=%d, NetIndex=%d\n", - *pLen, NetIndex)); - - return (PnmiStruct(pAC, IoC, SK_PNMI_SET, (char *)pBuf, - pLen, NetIndex)); -} - -/***************************************************************************** - * - * SkPnmiEvent - Event handler - * - * Description: - * Handles the following events: - * SK_PNMI_EVT_SIRQ_OVERFLOW When a hardware counter overflows an - * interrupt will be generated which is - * first handled by SIRQ which generates a - * this event. The event increments the - * upper 32 bit of the 64 bit counter. - * SK_PNMI_EVT_SEN_XXX The event is generated by the I2C module - * when a sensor reports a warning or - * error. The event will store a trap - * message in the trap buffer. - * SK_PNMI_EVT_CHG_EST_TIMER The timer event was initiated by this - * module and is used to calculate the - * port switches per hour. - * SK_PNMI_EVT_CLEAR_COUNTER The event clears all counters and - * timestamps. - * SK_PNMI_EVT_XMAC_RESET The event is generated by the driver - * before a hard reset of the XMAC is - * performed. All counters will be saved - * and added to the hardware counter - * values after reset to grant continuous - * counter values. - * SK_PNMI_EVT_RLMT_PORT_UP Generated by RLMT to notify that a port - * went logically up. A trap message will - * be stored to the trap buffer. - * SK_PNMI_EVT_RLMT_PORT_DOWN Generated by RLMT to notify that a port - * went logically down. A trap message will - * be stored to the trap buffer. - * SK_PNMI_EVT_RLMT_SEGMENTATION Generated by RLMT to notify that two - * spanning tree root bridges were - * detected. A trap message will be stored - * to the trap buffer. - * SK_PNMI_EVT_RLMT_ACTIVE_DOWN Notifies PNMI that an active port went - * down. PNMI will not further add the - * statistic values to the virtual port. - * SK_PNMI_EVT_RLMT_ACTIVE_UP Notifies PNMI that a port went up and - * is now an active port. PNMI will now - * add the statistic data of this port to - * the virtual port. - * SK_PNMI_EVT_RLMT_SET_NETS Notifies PNMI about the net mode. The first parameter - * contains the number of nets. 1 means single net, 2 means - * dual net. The second parameter is -1 - * - * Returns: - * Always 0 - */ -int SkPnmiEvent( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Event, /* Event-Id */ -SK_EVPARA Param) /* Event dependent parameter */ -{ - unsigned int PhysPortIndex; - unsigned int MaxNetNumber; - int CounterIndex; - int Ret; - SK_U16 MacStatus; - SK_U64 OverflowStatus; - SK_U64 Mask; - int MacType; - SK_U64 Value; - SK_U32 Val32; - SK_U16 Register; - SK_EVPARA EventParam; - SK_U64 NewestValue; - SK_U64 OldestValue; - SK_U64 Delta; - SK_PNMI_ESTIMATE *pEst; - SK_U32 NetIndex; - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; - SK_U32 RetCode; - int i; - SK_U32 CableLength; - - -#ifdef DEBUG - if (Event != SK_PNMI_EVT_XMAC_RESET) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: SkPnmiEvent: Called, Event=0x%x, Param=0x%x\n", - (unsigned int)Event, (unsigned int)Param.Para64)); - } -#endif /* DEBUG */ - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On call"); - - MacType = pAC->GIni.GIMacType; - - switch (Event) { - - case SK_PNMI_EVT_SIRQ_OVERFLOW: - PhysPortIndex = (int)Param.Para32[0]; - MacStatus = (SK_U16)Param.Para32[1]; -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SIRQ_OVERFLOW parameter" - " wrong, PhysPortIndex=0x%x\n", - PhysPortIndex)); - return (0); - } -#endif /* DEBUG */ - OverflowStatus = 0; - - /* - * Check which source caused an overflow interrupt. - */ - if ((pAC->GIni.GIFunc.pFnMacOverflow(pAC, IoC, PhysPortIndex, - MacStatus, &OverflowStatus) != 0) || - (OverflowStatus == 0)) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - - /* - * Check the overflow status register and increment - * the upper dword of corresponding counter. - */ - for (CounterIndex = 0; CounterIndex < sizeof(Mask) * 8; - CounterIndex ++) { - - Mask = (SK_U64)1 << CounterIndex; - if ((OverflowStatus & Mask) == 0) { - - continue; - } - - switch (StatOvrflwBit[CounterIndex][MacType]) { - - case SK_PNMI_HTX_UTILUNDER: - case SK_PNMI_HTX_UTILOVER: - if (MacType == SK_MAC_XMAC) { - XM_IN16(IoC, PhysPortIndex, XM_TX_CMD, &Register); - Register |= XM_TX_SAM_LINE; - XM_OUT16(IoC, PhysPortIndex, XM_TX_CMD, Register); - } - break; - - case SK_PNMI_HRX_UTILUNDER: - case SK_PNMI_HRX_UTILOVER: - if (MacType == SK_MAC_XMAC) { - XM_IN16(IoC, PhysPortIndex, XM_RX_CMD, &Register); - Register |= XM_RX_SAM_LINE; - XM_OUT16(IoC, PhysPortIndex, XM_RX_CMD, Register); - } - break; - - case SK_PNMI_HTX_OCTETHIGH: - case SK_PNMI_HTX_OCTETLOW: - case SK_PNMI_HTX_RESERVED: - case SK_PNMI_HRX_OCTETHIGH: - case SK_PNMI_HRX_OCTETLOW: - case SK_PNMI_HRX_IRLENGTH: - case SK_PNMI_HRX_RESERVED: - - /* - * the following counters aren't be handled (id > 63) - */ - case SK_PNMI_HTX_SYNC: - case SK_PNMI_HTX_SYNC_OCTET: - break; - - case SK_PNMI_HRX_LONGFRAMES: - if (MacType == SK_MAC_GMAC) { - pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[CounterIndex] ++; - } - break; - - default: - pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[CounterIndex] ++; - } - } - break; - - case SK_PNMI_EVT_SEN_WAR_LOW: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_LOW parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_LOW, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_WAR_UPP: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_WAR_UPP parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_WAR_UPP, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_ERR_LOW: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_LOW parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_LOW, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_SEN_ERR_UPP: -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= (unsigned int)pAC->I2c.MaxSens) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_SEN_ERR_UPP parameter wrong, SensorIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate - * an event for user space applications with the - * SK_DRIVER_SENDEVENT macro. - */ - QueueSensorTrap(pAC, OID_SKGE_TRAP_SEN_ERR_UPP, - (unsigned int)Param.Para64); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_CHG_EST_TIMER: - /* - * Calculate port switch average on a per hour basis - * Time interval for check : 28125 ms - * Number of values for average : 8 - * - * Be careful in changing these values, on change check - * - typedef of SK_PNMI_ESTIMATE (Size of EstValue - * array one less than value number) - * - Timer initialization SkTimerStart() in SkPnmiInit - * - Delta value below must be multiplicated with - * power of 2 - * - */ - pEst = &pAC->Pnmi.RlmtChangeEstimate; - CounterIndex = pEst->EstValueIndex + 1; - if (CounterIndex == 7) { - - CounterIndex = 0; - } - pEst->EstValueIndex = CounterIndex; - - NewestValue = pAC->Pnmi.RlmtChangeCts; - OldestValue = pEst->EstValue[CounterIndex]; - pEst->EstValue[CounterIndex] = NewestValue; - - /* - * Calculate average. Delta stores the number of - * port switches per 28125 * 8 = 225000 ms - */ - if (NewestValue >= OldestValue) { - - Delta = NewestValue - OldestValue; - } - else { - /* Overflow situation */ - Delta = (SK_U64)(0 - OldestValue) + NewestValue; - } - - /* - * Extrapolate delta to port switches per hour. - * Estimate = Delta * (3600000 / 225000) - * = Delta * 16 - * = Delta << 4 - */ - pAC->Pnmi.RlmtChangeEstimate.Estimate = Delta << 4; - - /* - * Check if threshold is exceeded. If the threshold is - * permanently exceeded every 28125 ms an event will be - * generated to remind the user of this condition. - */ - if ((pAC->Pnmi.RlmtChangeThreshold != 0) && - (pAC->Pnmi.RlmtChangeEstimate.Estimate >= - pAC->Pnmi.RlmtChangeThreshold)) { - - QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_CHANGE_THRES); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - } - - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - SkTimerStart(pAC, IoC, &pAC->Pnmi.RlmtChangeEstimate.EstTimer, - 28125000, SKGE_PNMI, SK_PNMI_EVT_CHG_EST_TIMER, - EventParam); - break; - - case SK_PNMI_EVT_CLEAR_COUNTER: - /* - * Param.Para32[0] contains the NetIndex (0 ..1). - * Param.Para32[1] is reserved, contains -1. - */ - NetIndex = (SK_U32)Param.Para32[0]; - -#ifdef DEBUG - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_CLEAR_COUNTER parameter wrong, NetIndex=%d\n", - NetIndex)); - - return (0); - } -#endif /* DEBUG */ - - /* - * Set all counters and timestamps to zero. - * The according NetIndex is required as a - * parameter of the event. - */ - ResetCounter(pAC, IoC, NetIndex); - break; - - case SK_PNMI_EVT_XMAC_RESET: - /* - * To grant continuous counter values store the current - * XMAC statistic values to the entries 1..n of the - * CounterOffset array. XMAC Errata #2 - */ -#ifdef DEBUG - if ((unsigned int)Param.Para64 >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_XMAC_RESET parameter wrong, PhysPortIndex=%d\n", - (unsigned int)Param.Para64)); - return (0); - } -#endif - PhysPortIndex = (unsigned int)Param.Para64; - - /* - * Update XMAC statistic to get fresh values - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - /* - * Increment semaphore to indicate that an update was - * already done - */ - pAC->Pnmi.MacUpdatedFlag ++; - - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - pAC->Pnmi.Port[PhysPortIndex].CounterOffset[CounterIndex] = - GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); - - pAC->Pnmi.Port[PhysPortIndex].CounterHigh[CounterIndex] = 0; - } - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_PORT_UP: - PhysPortIndex = (unsigned int)Param.Para32[0]; -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_UP parameter" - " wrong, PhysPortIndex=%d\n", PhysPortIndex)); - - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_UP, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* Bugfix for XMAC errata (#10620)*/ - if (MacType == SK_MAC_XMAC) { - /* Add incremental difference to offset (#10620)*/ - (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, - XM_RXE_SHT_ERR, &Val32); - - Value = (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); - pAC->Pnmi.Port[PhysPortIndex].CounterOffset[SK_PNMI_HRX_SHORTS] += - Value - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark; - } - - /* Tell VctStatus() that a link was up meanwhile. */ - pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_LINK; - break; - - case SK_PNMI_EVT_RLMT_PORT_DOWN: - PhysPortIndex = (unsigned int)Param.Para32[0]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_PORT_DOWN parameter" - " wrong, PhysPortIndex=%d\n", PhysPortIndex)); - - return (0); - } -#endif /* DEBUG */ - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtPortTrap(pAC, OID_SKGE_TRAP_RLMT_PORT_DOWN, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* Bugfix #10620 - get zero level for incremental difference */ - if (MacType == SK_MAC_XMAC) { - - (void)pAC->GIni.GIFunc.pFnMacStatistic(pAC, IoC, PhysPortIndex, - XM_RXE_SHT_ERR, &Val32); - - pAC->Pnmi.Port[PhysPortIndex].RxShortZeroMark = - (((SK_U64)pAC->Pnmi.Port[PhysPortIndex]. - CounterHigh[SK_PNMI_HRX_SHORTS] << 32) | (SK_U64)Val32); - } - break; - - case SK_PNMI_EVT_RLMT_ACTIVE_DOWN: - PhysPortIndex = (unsigned int)Param.Para32[0]; - NetIndex = (SK_U32)Param.Para32[1]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, PhysPort=%d\n", - PhysPortIndex)); - } - - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_DOWN parameter too high, NetIndex=%d\n", - NetIndex)); - } -#endif /* DEBUG */ - - /* - * For now, ignore event if NetIndex != 0. - */ - if (Param.Para32[1] != 0) { - - return (0); - } - - /* - * Nothing to do if port is already inactive - */ - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - return (0); - } - - /* - * Update statistic counters to calculate new offset for the virtual - * port and increment semaphore to indicate that an update was already - * done. - */ - if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != - SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Calculate new counter offset for virtual port to grant continous - * counting on port switches. The virtual port consists of all currently - * active ports. The port down event indicates that a port is removed - * from the virtual port. Therefore add the counter value of the removed - * port to the CounterOffset for the virtual port to grant the same - * counter value. - */ - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); - - pAC->Pnmi.VirtualCounterOffset[CounterIndex] += Value; - } - - /* - * Set port to inactive - */ - pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_FALSE; - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_ACTIVE_UP: - PhysPortIndex = (unsigned int)Param.Para32[0]; - NetIndex = (SK_U32)Param.Para32[1]; - -#ifdef DEBUG - if (PhysPortIndex >= SK_MAX_MACS) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, PhysPort=%d\n", - PhysPortIndex)); - } - - if (NetIndex >= pAC->Rlmt.NumNets) { - - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_CTRL, - ("PNMI: ERR: SkPnmiEvent: SK_PNMI_EVT_RLMT_ACTIVE_UP parameter too high, NetIndex=%d\n", - NetIndex)); - } -#endif /* DEBUG */ - - /* - * For now, ignore event if NetIndex != 0. - */ - if (Param.Para32[1] != 0) { - - return (0); - } - - /* - * Nothing to do if port is already active - */ - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - return (0); - } - - /* - * Statistic maintenance - */ - pAC->Pnmi.RlmtChangeCts ++; - pAC->Pnmi.RlmtChangeTime = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueRlmtNewMacTrap(pAC, PhysPortIndex); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - - /* - * Update statistic counters to calculate new offset for the virtual - * port and increment semaphore to indicate that an update was - * already done. - */ - if (MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1) != - SK_PNMI_ERR_OK) { - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Calculate new counter offset for virtual port to grant continous - * counting on port switches. A new port is added to the virtual port. - * Therefore substract the counter value of the new port from the - * CounterOffset for the virtual port to grant the same value. - */ - for (CounterIndex = 0; CounterIndex < SK_PNMI_MAX_IDX; - CounterIndex ++) { - - if (!StatAddr[CounterIndex][MacType].GetOffset) { - - continue; - } - - Value = GetPhysStatVal(pAC, IoC, PhysPortIndex, CounterIndex); - - pAC->Pnmi.VirtualCounterOffset[CounterIndex] -= Value; - } - - /* Set port to active */ - pAC->Pnmi.Port[PhysPortIndex].ActiveFlag = SK_TRUE; - - pAC->Pnmi.MacUpdatedFlag --; - break; - - case SK_PNMI_EVT_RLMT_SEGMENTATION: - /* - * Para.Para32[0] contains the NetIndex. - */ - - /* - * Store a trap message in the trap buffer and generate an event for - * user space applications with the SK_DRIVER_SENDEVENT macro. - */ - QueueSimpleTrap(pAC, OID_SKGE_TRAP_RLMT_SEGMENTATION); - (void)SK_DRIVER_SENDEVENT(pAC, IoC); - break; - - case SK_PNMI_EVT_RLMT_SET_NETS: - /* - * Param.Para32[0] contains the number of Nets. - * Param.Para32[1] is reserved, contains -1. - */ - /* - * Check number of nets - */ - MaxNetNumber = pAC->GIni.GIMacsFound; - if (((unsigned int)Param.Para32[0] < 1) - || ((unsigned int)Param.Para32[0] > MaxNetNumber)) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - if ((unsigned int)Param.Para32[0] == 1) { /* single net mode */ - pAC->Pnmi.DualNetActiveFlag = SK_FALSE; - } - else { /* dual net mode */ - pAC->Pnmi.DualNetActiveFlag = SK_TRUE; - } - break; - - case SK_PNMI_EVT_VCT_RESET: - PhysPortIndex = Param.Para32[0]; - pPrt = &pAC->GIni.GP[PhysPortIndex]; - pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; - - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 2) { - /* - * VCT test is still running. - * Start VCT timer counter again. - */ - SK_MEMSET((char *) &Param, 0, sizeof(Param)); - Param.Para32[0] = PhysPortIndex; - Param.Para32[1] = -1; - SkTimerStart(pAC, IoC, - &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, - 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Param); - break; - } - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] |= - (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); - - /* Copy results for later use to PNMI struct. */ - for (i = 0; i < 4; i++) { - if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { - if ((pPrt->PMdiPairLen[i] > 35) && - (pPrt->PMdiPairLen[i] < 0xff)) { - pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; - } - } - if ((pPrt->PMdiPairLen[i] > 35) && - (pPrt->PMdiPairLen[i] != 0xff)) { - CableLength = 1000 * - (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); - } - else { - CableLength = 0; - } - pVctBackupData->PMdiPairLen[i] = CableLength; - pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; - } - - Param.Para32[0] = PhysPortIndex; - Param.Para32[1] = -1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Param); - SkEventDispatcher(pAC, IoC); - } - - break; - - default: - break; - } - - SK_PNMI_CHECKFLAGS("SkPnmiEvent: On return"); - return (0); -} - - -/****************************************************************************** - * - * Private functions - * - */ - -/***************************************************************************** - * - * PnmiVar - Gets, presets, and sets single OIDs - * - * Description: - * Looks up the requested OID, calls the corresponding handler - * function, and passes the parameters with the get, preset, or - * set command. The function is called by SkGePnmiGetVar, - * SkGePnmiPreSetVar, or SkGePnmiSetVar. - * - * Returns: - * SK_PNMI_ERR_XXX. For details have a look at the description of the - * calling functions. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -PNMI_STATIC int PnmiVar( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* Total length of pBuf management data */ -SK_U32 Instance, /* Instance (1..n) that is to be set or -1 */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int TableIndex; - int Ret; - - - if ((TableIndex = LookupId(Id)) == (unsigned int)(-1)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_OID); - } - - /* Check NetIndex */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - SK_PNMI_CHECKFLAGS("PnmiVar: On call"); - - Ret = IdTable[TableIndex].Func(pAC, IoC, Action, Id, pBuf, pLen, - Instance, TableIndex, NetIndex); - - SK_PNMI_CHECKFLAGS("PnmiVar: On return"); - - return (Ret); -} - -/***************************************************************************** - * - * PnmiStruct - Presets and Sets data in structure SK_PNMI_STRUCT_DATA - * - * Description: - * The return value of the function will also be stored in - * SK_PNMI_STRUCT_DATA if the passed buffer has the minimum size of - * SK_PNMI_MIN_STRUCT_SIZE. The sub-function runs through the IdTable, - * checks which OIDs are able to set, and calls the handler function of - * the OID to perform the set. The return value of the function will - * also be stored in SK_PNMI_STRUCT_DATA if the passed buffer has the - * minimum size of SK_PNMI_MIN_STRUCT_SIZE. The function is called - * by SkGePnmiPreSetStruct and SkGePnmiSetStruct. - * - * Returns: - * SK_PNMI_ERR_XXX. The codes are described in the calling functions. - * SK_PNMI_ERR_UNKNOWN_NET The requested NetIndex doesn't exist - */ -PNMI_STATIC int PnmiStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* PRESET/SET action to be performed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* Length of pBuf management data buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int TableIndex; - unsigned int DstOffset; - unsigned int Len; - unsigned int InstanceNo; - unsigned int InstanceCnt; - SK_U32 Instance; - SK_U32 Id; - - - /* Check if the passed buffer has the right size */ - if (*pLen < SK_PNMI_STRUCT_SIZE) { - - /* Check if we can return the error within the buffer */ - if (*pLen >= SK_PNMI_MIN_STRUCT_SIZE) { - - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_TOO_SHORT, - (SK_U32)(-1)); - } - - *pLen = SK_PNMI_STRUCT_SIZE; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* Check NetIndex */ - if (NetIndex >= pAC->Rlmt.NumNets) { - return (SK_PNMI_ERR_UNKNOWN_NET); - } - - SK_PNMI_CHECKFLAGS("PnmiStruct: On call"); - - /* - * Update the values of RLMT and SIRQ and increment semaphores to - * indicate that an update was already done. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - SK_PNMI_SET_STAT(pBuf, Ret, (SK_U32)(-1)); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (Ret); - } - - pAC->Pnmi.RlmtUpdatedFlag ++; - pAC->Pnmi.SirqUpdatedFlag ++; - - /* Preset/Set values */ - for (TableIndex = 0; TableIndex < ID_TABLE_SIZE; TableIndex ++) { - - if ((IdTable[TableIndex].Access != SK_PNMI_RW) && - (IdTable[TableIndex].Access != SK_PNMI_WO)) { - - continue; - } - - InstanceNo = IdTable[TableIndex].InstanceNo; - Id = IdTable[TableIndex].Id; - - for (InstanceCnt = 1; InstanceCnt <= InstanceNo; - InstanceCnt ++) { - - DstOffset = IdTable[TableIndex].Offset + - (InstanceCnt - 1) * - IdTable[TableIndex].StructSize; - - /* - * Because VPD multiple instance variables are - * not setable we do not need to evaluate VPD - * instances. Have a look to VPD instance - * calculation in SkPnmiGetStruct(). - */ - Instance = (SK_U32)InstanceCnt; - - /* - * Evaluate needed buffer length - */ - Len = 0; - Ret = IdTable[TableIndex].Func(pAC, IoC, - SK_PNMI_GET, IdTable[TableIndex].Id, - NULL, &Len, Instance, TableIndex, NetIndex); - - if (Ret == SK_PNMI_ERR_UNKNOWN_INST) { - - break; - } - if (Ret != SK_PNMI_ERR_TOO_SHORT) { - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, - SK_PNMI_ERR_GENERAL, DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_GENERAL); - } - if (Id == OID_SKGE_VPD_ACTION) { - - switch (*(pBuf + DstOffset)) { - - case SK_PNMI_VPD_CREATE: - Len = 3 + *(pBuf + DstOffset + 3); - break; - - case SK_PNMI_VPD_DELETE: - Len = 3; - break; - - default: - Len = 1; - break; - } - } - - /* Call the OID handler function */ - Ret = IdTable[TableIndex].Func(pAC, IoC, Action, - IdTable[TableIndex].Id, pBuf + DstOffset, - &Len, Instance, TableIndex, NetIndex); - - if (Ret != SK_PNMI_ERR_OK) { - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_BAD_VALUE, - DstOffset); - *pLen = SK_PNMI_MIN_STRUCT_SIZE; - return (SK_PNMI_ERR_BAD_VALUE); - } - } - } - - pAC->Pnmi.RlmtUpdatedFlag --; - pAC->Pnmi.SirqUpdatedFlag --; - - SK_PNMI_CHECKFLAGS("PnmiStruct: On return"); - SK_PNMI_SET_STAT(pBuf, SK_PNMI_ERR_OK, (SK_U32)(-1)); - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * LookupId - Lookup an OID in the IdTable - * - * Description: - * Scans the IdTable to find the table entry of an OID. - * - * Returns: - * The table index or -1 if not found. - */ -PNMI_STATIC int LookupId( -SK_U32 Id) /* Object identifier to be searched */ -{ - int i; - - for (i = 0; i < ID_TABLE_SIZE; i++) { - - if (IdTable[i].Id == Id) { - - return i; - } - } - - return (-1); -} - -/***************************************************************************** - * - * OidStruct - Handler of OID_SKGE_ALL_DATA - * - * Description: - * This OID performs a Get/Preset/SetStruct call and returns all data - * in a SK_PNMI_STRUCT_DATA structure. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int OidStruct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - if (Id != OID_SKGE_ALL_DATA) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR003, - SK_PNMI_ERR003MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - switch (Action) { - - case SK_PNMI_GET: - return (SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - - case SK_PNMI_PRESET: - return (SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - - case SK_PNMI_SET: - return (SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex)); - } - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR004, SK_PNMI_ERR004MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); -} - -/***************************************************************************** - * - * Perform - OID handler of OID_SKGE_ACTION - * - * Description: - * None. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Perform( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - SK_U32 ActionOp; - - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* Check if a get should be performed */ - if (Action == SK_PNMI_GET) { - - /* A get is easy. We always return the same value */ - ActionOp = (SK_U32)SK_PNMI_ACT_IDLE; - SK_PNMI_STORE_U32(pBuf, ActionOp); - *pLen = sizeof(SK_U32); - - return (SK_PNMI_ERR_OK); - } - - /* Continue with PRESET/SET action */ - if (*pLen > sizeof(SK_U32)) { - - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* Check if the command is a known one */ - SK_PNMI_READ_U32(pBuf, ActionOp); - if (*pLen > sizeof(SK_U32) || - (ActionOp != SK_PNMI_ACT_IDLE && - ActionOp != SK_PNMI_ACT_RESET && - ActionOp != SK_PNMI_ACT_SELFTEST && - ActionOp != SK_PNMI_ACT_RESETCNT)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - switch (ActionOp) { - - case SK_PNMI_ACT_IDLE: - /* Nothing to do */ - break; - - case SK_PNMI_ACT_RESET: - /* - * Perform a driver reset or something that comes near - * to this. - */ - Ret = SK_DRIVER_RESET(pAC, IoC); - if (Ret != 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR005, - SK_PNMI_ERR005MSG); - - return (SK_PNMI_ERR_GENERAL); - } - break; - - case SK_PNMI_ACT_SELFTEST: - /* - * Perform a driver selftest or something similar to this. - * Currently this feature is not used and will probably - * implemented in another way. - */ - Ret = SK_DRIVER_SELFTEST(pAC, IoC); - pAC->Pnmi.TestResult = Ret; - break; - - case SK_PNMI_ACT_RESETCNT: - /* Set all counters and timestamps to zero */ - ResetCounter(pAC, IoC, NetIndex); - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR006, - SK_PNMI_ERR006MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Mac8023Stat - OID handler of OID_GEN_XXX and OID_802_3_XXX - * - * Description: - * Retrieves the statistic values of the virtual port (logical - * index 0). Only special OIDs of NDIS are handled which consist - * of a 32 bit instead of a 64 bit value. The OIDs are public - * because perhaps some other platform can use them too. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Mac8023Stat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - SK_U64 StatVal; - SK_U32 StatVal32; - SK_BOOL Is64BitReq = SK_FALSE; - - /* - * Only the active Mac is returned - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Check action type - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check length */ - switch (Id) { - - case OID_802_3_PERMANENT_ADDRESS: - case OID_802_3_CURRENT_ADDRESS: - if (*pLen < sizeof(SK_MAC_ADDR)) { - - *pLen = sizeof(SK_MAC_ADDR); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: -#ifndef SK_NDIS_64BIT_CTR - if (*pLen < sizeof(SK_U32)) { - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - -#else /* SK_NDIS_64BIT_CTR */ - - /* for compatibility, at least 32bit are required for OID */ - if (*pLen < sizeof(SK_U32)) { - /* - * but indicate handling for 64bit values, - * if insufficient space is provided - */ - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; -#endif /* SK_NDIS_64BIT_CTR */ - break; - } - - /* - * Update all statistics, because we retrieve virtual MAC, which - * consists of multiple physical statistics and increment semaphore - * to indicate that an update was already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if ( Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Get value (MAC Index 0 identifies the virtual MAC) - */ - switch (Id) { - - case OID_802_3_PERMANENT_ADDRESS: - CopyMac(pBuf, &pAC->Addr.Net[NetIndex].PermanentMacAddress); - *pLen = sizeof(SK_MAC_ADDR); - break; - - case OID_802_3_CURRENT_ADDRESS: - CopyMac(pBuf, &pAC->Addr.Net[NetIndex].CurrentMacAddress); - *pLen = sizeof(SK_MAC_ADDR); - break; - - default: - StatVal = GetStatVal(pAC, IoC, 0, IdTable[TableIndex].Param, NetIndex); - - /* by default 32bit values are evaluated */ - if (!Is64BitReq) { - StatVal32 = (SK_U32)StatVal; - SK_PNMI_STORE_U32(pBuf, StatVal32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, StatVal); - *pLen = sizeof(SK_U64); - } - break; - } - - pAC->Pnmi.MacUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacPrivateStat - OID handler function of OID_SKGE_STAT_XXX - * - * Description: - * Retrieves the MAC statistic data. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int MacPrivateStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int LogPortMax; - unsigned int LogPortIndex; - unsigned int PhysPortMax; - unsigned int Limit; - unsigned int Offset; - int MacType; - int Ret; - SK_U64 StatVal; - - - - /* Calculate instance if wished. MAC index 0 is the virtual MAC */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - MacType = pAC->GIni.GIMacType; - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - /* Check action */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check length */ - if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U64)) { - - *pLen = (Limit - LogPortIndex) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Update MAC statistic and increment semaphore to indicate that - * an update was already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* Get value */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - -/* XXX not yet implemented due to XMAC problems - case OID_SKGE_STAT_TX_UTIL: - return (SK_PNMI_ERR_GENERAL); -*/ -/* XXX not yet implemented due to XMAC problems - case OID_SKGE_STAT_RX_UTIL: - return (SK_PNMI_ERR_GENERAL); -*/ - case OID_SKGE_STAT_RX: - if (MacType == SK_MAC_GMAC) { - StatVal = - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_BROADCAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_MULTICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_UNICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HRX_UNDERSIZE, NetIndex); - } - else { - StatVal = GetStatVal(pAC, IoC, LogPortIndex, - IdTable[TableIndex].Param, NetIndex); - } - break; - - case OID_SKGE_STAT_TX: - if (MacType == SK_MAC_GMAC) { - StatVal = - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_BROADCAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_MULTICAST, NetIndex) + - GetStatVal(pAC, IoC, LogPortIndex, - SK_PNMI_HTX_UNICAST, NetIndex); - } - else { - StatVal = GetStatVal(pAC, IoC, LogPortIndex, - IdTable[TableIndex].Param, NetIndex); - } - break; - - default: - StatVal = GetStatVal(pAC, IoC, LogPortIndex, - IdTable[TableIndex].Param, NetIndex); - } - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); - - Offset += sizeof(SK_U64); - } - *pLen = Offset; - - pAC->Pnmi.MacUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Addr - OID handler function of OID_SKGE_PHYS_CUR_ADDR and _FAC_ADDR - * - * Description: - * Get/Presets/Sets the current and factory MAC address. The MAC - * address of the virtual port, which is reported to the OS, may - * not be changed, but the physical ones. A set to the virtual port - * will be ignored. No error should be reported because otherwise - * a multiple instance set (-1) would always fail. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Addr( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int LogPortMax; - unsigned int PhysPortMax; - unsigned int LogPortIndex; - unsigned int PhysPortIndex; - unsigned int Limit; - unsigned int Offset = 0; - - /* - * Calculate instance if wished. MAC index 0 is the virtual - * MAC. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - /* - * Perform Action - */ - if (Action == SK_PNMI_GET) { - - /* Check length */ - if (*pLen < (Limit - LogPortIndex) * 6) { - - *pLen = (Limit - LogPortIndex) * 6; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get value - */ - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - - case OID_SKGE_PHYS_CUR_ADDR: - if (LogPortIndex == 0) { - CopyMac(pBuf + Offset, &pAC->Addr.Net[NetIndex].CurrentMacAddress); - } - else { - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); - - CopyMac(pBuf + Offset, - &pAC->Addr.Port[PhysPortIndex].CurrentMacAddress); - } - Offset += 6; - break; - - case OID_SKGE_PHYS_FAC_ADDR: - if (LogPortIndex == 0) { - CopyMac(pBuf + Offset, - &pAC->Addr.Net[NetIndex].PermanentMacAddress); - } - else { - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - CopyMac(pBuf + Offset, - &pAC->Addr.Port[PhysPortIndex].PermanentMacAddress); - } - Offset += 6; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR008, - SK_PNMI_ERR008MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - *pLen = Offset; - } - else { - /* - * The logical MAC address may not be changed only - * the physical ones - */ - if (Id == OID_SKGE_PHYS_FAC_ADDR) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Only the current address may be changed - */ - if (Id != OID_SKGE_PHYS_CUR_ADDR) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR009, - SK_PNMI_ERR009MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Check length */ - if (*pLen < (Limit - LogPortIndex) * 6) { - - *pLen = (Limit - LogPortIndex) * 6; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen > (Limit - LogPortIndex) * 6) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* - * Check Action - */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - - /* - * Set OID_SKGE_MAC_CUR_ADDR - */ - for (; LogPortIndex < Limit; LogPortIndex ++, Offset += 6) { - - /* - * A set to virtual port and set of broadcast - * address will be ignored - */ - if (LogPortIndex == 0 || SK_MEMCMP(pBuf + Offset, - "\xff\xff\xff\xff\xff\xff", 6) == 0) { - - continue; - } - - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, - LogPortIndex); - - Ret = SkAddrOverride(pAC, IoC, PhysPortIndex, - (SK_MAC_ADDR *)(pBuf + Offset), - (LogPortIndex == 0 ? SK_ADDR_VIRTUAL_ADDRESS : - SK_ADDR_PHYSICAL_ADDRESS)); - if (Ret != SK_ADDR_OVERRIDE_SUCCESS) { - - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * CsumStat - OID handler function of OID_SKGE_CHKSM_XXX - * - * Description: - * Retrieves the statistic values of the CSUM module. The CSUM data - * structure must be available in the SK_AC even if the CSUM module - * is not included, because PNMI reads the statistic data from the - * CSUM part of SK_AC directly. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int CsumStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int Index; - unsigned int Limit; - unsigned int Offset = 0; - SK_U64 StatVal; - - - /* - * Calculate instance if wished - */ - if (Instance != (SK_U32)(-1)) { - - if ((Instance < 1) || (Instance > SKCS_NUM_PROTOCOLS)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - Index = (unsigned int)Instance - 1; - Limit = Index + 1; - } - else { - Index = 0; - Limit = SKCS_NUM_PROTOCOLS; - } - - /* - * Check action - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check length */ - if (*pLen < (Limit - Index) * sizeof(SK_U64)) { - - *pLen = (Limit - Index) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get value - */ - for (; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_CHKSM_RX_OK_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxOkCts; - break; - - case OID_SKGE_CHKSM_RX_UNABLE_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxUnableCts; - break; - - case OID_SKGE_CHKSM_RX_ERR_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].RxErrCts; - break; - - case OID_SKGE_CHKSM_TX_OK_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxOkCts; - break; - - case OID_SKGE_CHKSM_TX_UNABLE_CTS: - StatVal = pAC->Csum.ProtoStats[NetIndex][Index].TxUnableCts; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR010, - SK_PNMI_ERR010MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - SK_PNMI_STORE_U64(pBuf + Offset, StatVal); - Offset += sizeof(SK_U64); - } - - /* - * Store used buffer space - */ - *pLen = Offset; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SensorStat - OID handler function of OID_SKGE_SENSOR_XXX - * - * Description: - * Retrieves the statistic values of the I2C module, which handles - * the temperature and voltage sensors. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int SensorStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int i; - unsigned int Index; - unsigned int Limit; - unsigned int Offset; - unsigned int Len; - SK_U32 Val32; - SK_U64 Val64; - - - /* - * Calculate instance if wished - */ - if ((Instance != (SK_U32)(-1))) { - - if ((Instance < 1) || (Instance > (SK_U32)pAC->I2c.MaxSens)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - Index = (unsigned int)Instance -1; - Limit = (unsigned int)Instance; - } - else { - Index = 0; - Limit = (unsigned int) pAC->I2c.MaxSens; - } - - /* - * Check action - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check length */ - switch (Id) { - - case OID_SKGE_SENSOR_VALUE: - case OID_SKGE_SENSOR_WAR_THRES_LOW: - case OID_SKGE_SENSOR_WAR_THRES_UPP: - case OID_SKGE_SENSOR_ERR_THRES_LOW: - case OID_SKGE_SENSOR_ERR_THRES_UPP: - if (*pLen < (Limit - Index) * sizeof(SK_U32)) { - - *pLen = (Limit - Index) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_DESCR: - for (Offset = 0, i = Index; i < Limit; i ++) { - - Len = (unsigned int) - SK_STRLEN(pAC->I2c.SenTable[i].SenDesc) + 1; - if (Len >= SK_PNMI_STRINGLEN2) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR011, - SK_PNMI_ERR011MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - Offset += Len; - } - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_INDEX: - case OID_SKGE_SENSOR_TYPE: - case OID_SKGE_SENSOR_STATUS: - if (*pLen < Limit - Index) { - - *pLen = Limit - Index; - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_SENSOR_WAR_CTS: - case OID_SKGE_SENSOR_WAR_TIME: - case OID_SKGE_SENSOR_ERR_CTS: - case OID_SKGE_SENSOR_ERR_TIME: - if (*pLen < (Limit - Index) * sizeof(SK_U64)) { - - *pLen = (Limit - Index) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR012, - SK_PNMI_ERR012MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - - } - - /* - * Get value - */ - for (Offset = 0; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_SENSOR_INDEX: - *(pBuf + Offset) = (char)Index; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_DESCR: - Len = SK_STRLEN(pAC->I2c.SenTable[Index].SenDesc); - SK_MEMCPY(pBuf + Offset + 1, - pAC->I2c.SenTable[Index].SenDesc, Len); - *(pBuf + Offset) = (char)Len; - Offset += Len + 1; - break; - - case OID_SKGE_SENSOR_TYPE: - *(pBuf + Offset) = - (char)pAC->I2c.SenTable[Index].SenType; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_VALUE: - Val32 = (SK_U32)pAC->I2c.SenTable[Index].SenValue; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_WAR_THRES_LOW: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreWarnLow; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_WAR_THRES_UPP: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreWarnHigh; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_ERR_THRES_LOW: - Val32 = (SK_U32)pAC->I2c.SenTable[Index]. - SenThreErrLow; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_ERR_THRES_UPP: - Val32 = pAC->I2c.SenTable[Index].SenThreErrHigh; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_STATUS: - *(pBuf + Offset) = - (char)pAC->I2c.SenTable[Index].SenErrFlag; - Offset += sizeof(char); - break; - - case OID_SKGE_SENSOR_WAR_CTS: - Val64 = pAC->I2c.SenTable[Index].SenWarnCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_ERR_CTS: - Val64 = pAC->I2c.SenTable[Index].SenErrCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_WAR_TIME: - Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. - SenBegWarnTS); - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_SENSOR_ERR_TIME: - Val64 = SK_PNMI_HUNDREDS_SEC(pAC->I2c.SenTable[Index]. - SenBegErrTS); - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("SensorStat: Unknown OID should be handled before")); - - return (SK_PNMI_ERR_GENERAL); - } - } - - /* - * Store used buffer space - */ - *pLen = Offset; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Vpd - OID handler function of OID_SKGE_VPD_XXX - * - * Description: - * Get/preset/set of VPD data. As instance the name of a VPD key - * can be passed. The Instance parameter is a SK_U32 and can be - * used as a string buffer for the VPD key, because their maximum - * length is 4 byte. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Vpd( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_VPD_STATUS *pVpdStatus; - unsigned int BufLen; - char Buf[256]; - char KeyArr[SK_PNMI_VPD_ENTRIES][SK_PNMI_VPD_KEY_SIZE]; - char KeyStr[SK_PNMI_VPD_KEY_SIZE]; - unsigned int KeyNo; - unsigned int Offset; - unsigned int Index; - unsigned int FirstIndex; - unsigned int LastIndex; - unsigned int Len; - int Ret; - SK_U32 Val32; - - /* - * Get array of all currently stored VPD keys - */ - Ret = GetVpdKeyArr(pAC, IoC, &KeyArr[0][0], sizeof(KeyArr), &KeyNo); - if (Ret != SK_PNMI_ERR_OK) { - *pLen = 0; - return (Ret); - } - - /* - * If instance is not -1, try to find the requested VPD key for - * the multiple instance variables. The other OIDs as for example - * OID VPD_ACTION are single instance variables and must be - * handled separatly. - */ - FirstIndex = 0; - LastIndex = KeyNo; - - if ((Instance != (SK_U32)(-1))) { - - if (Id == OID_SKGE_VPD_KEY || Id == OID_SKGE_VPD_VALUE || - Id == OID_SKGE_VPD_ACCESS) { - - SK_STRNCPY(KeyStr, (char *)&Instance, 4); - KeyStr[4] = 0; - - for (Index = 0; Index < KeyNo; Index ++) { - - if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { - FirstIndex = Index; - LastIndex = Index+1; - break; - } - } - if (Index == KeyNo) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - } - else if (Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - } - - /* - * Get value, if a query should be performed - */ - if (Action == SK_PNMI_GET) { - - switch (Id) { - - case OID_SKGE_VPD_FREE_BYTES: - /* Check length of buffer */ - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Get number of free bytes */ - pVpdStatus = VpdStat(pAC, IoC); - if (pVpdStatus == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR017, - SK_PNMI_ERR017MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - if ((pVpdStatus->vpd_status & VPD_VALID) == 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR018, - SK_PNMI_ERR018MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Val32 = (SK_U32)pVpdStatus->vpd_free_rw; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_VPD_ENTRIES_LIST: - /* Check length */ - for (Len = 0, Index = 0; Index < KeyNo; Index ++) { - - Len += SK_STRLEN(KeyArr[Index]) + 1; - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* Get value */ - *(pBuf) = (char)Len - 1; - for (Offset = 1, Index = 0; Index < KeyNo; Index ++) { - - Len = SK_STRLEN(KeyArr[Index]); - SK_MEMCPY(pBuf + Offset, KeyArr[Index], Len); - - Offset += Len; - - if (Index < KeyNo - 1) { - - *(pBuf + Offset) = ' '; - Offset ++; - } - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ENTRIES_NUMBER: - /* Check length */ - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Val32 = (SK_U32)KeyNo; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_VPD_KEY: - /* Check buffer length, if it is large enough */ - for (Len = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - Len += SK_STRLEN(KeyArr[Index]) + 1; - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get the key to an intermediate buffer, because - * we have to prepend a length byte. - */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - Len = SK_STRLEN(KeyArr[Index]); - - *(pBuf + Offset) = (char)Len; - SK_MEMCPY(pBuf + Offset + 1, KeyArr[Index], - Len); - Offset += Len + 1; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_VALUE: - /* Check the buffer length if it is large enough */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - BufLen = 256; - if (VpdRead(pAC, IoC, KeyArr[Index], Buf, - (int *)&BufLen) > 0 || - BufLen >= SK_PNMI_VPD_DATALEN) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR021, - SK_PNMI_ERR021MSG); - - return (SK_PNMI_ERR_GENERAL); - } - Offset += BufLen + 1; - } - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * Get the value to an intermediate buffer, because - * we have to prepend a length byte. - */ - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - BufLen = 256; - if (VpdRead(pAC, IoC, KeyArr[Index], Buf, - (int *)&BufLen) > 0 || - BufLen >= SK_PNMI_VPD_DATALEN) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR022, - SK_PNMI_ERR022MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - *(pBuf + Offset) = (char)BufLen; - SK_MEMCPY(pBuf + Offset + 1, Buf, BufLen); - Offset += BufLen + 1; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ACCESS: - if (*pLen < LastIndex - FirstIndex) { - - *pLen = LastIndex - FirstIndex; - return (SK_PNMI_ERR_TOO_SHORT); - } - - for (Offset = 0, Index = FirstIndex; - Index < LastIndex; Index ++) { - - if (VpdMayWrite(KeyArr[Index])) { - - *(pBuf + Offset) = SK_PNMI_VPD_RW; - } - else { - *(pBuf + Offset) = SK_PNMI_VPD_RO; - } - Offset ++; - } - *pLen = Offset; - break; - - case OID_SKGE_VPD_ACTION: - Offset = LastIndex - FirstIndex; - if (*pLen < Offset) { - - *pLen = Offset; - return (SK_PNMI_ERR_TOO_SHORT); - } - SK_MEMSET(pBuf, 0, Offset); - *pLen = Offset; - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR023, - SK_PNMI_ERR023MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - else { - /* The only OID which can be set is VPD_ACTION */ - if (Id != OID_SKGE_VPD_ACTION) { - - if (Id == OID_SKGE_VPD_FREE_BYTES || - Id == OID_SKGE_VPD_ENTRIES_LIST || - Id == OID_SKGE_VPD_ENTRIES_NUMBER || - Id == OID_SKGE_VPD_KEY || - Id == OID_SKGE_VPD_VALUE || - Id == OID_SKGE_VPD_ACCESS) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR024, - SK_PNMI_ERR024MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * From this point we handle VPD_ACTION. Check the buffer - * length. It should at least have the size of one byte. - */ - if (*pLen < 1) { - - *pLen = 1; - return (SK_PNMI_ERR_TOO_SHORT); - } - - /* - * The first byte contains the VPD action type we should - * perform. - */ - switch (*pBuf) { - - case SK_PNMI_VPD_IGNORE: - /* Nothing to do */ - break; - - case SK_PNMI_VPD_CREATE: - /* - * We have to create a new VPD entry or we modify - * an existing one. Check first the buffer length. - */ - if (*pLen < 4) { - - *pLen = 4; - return (SK_PNMI_ERR_TOO_SHORT); - } - KeyStr[0] = pBuf[1]; - KeyStr[1] = pBuf[2]; - KeyStr[2] = 0; - - /* - * Is the entry writable or does it belong to the - * read-only area? - */ - if (!VpdMayWrite(KeyStr)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - Offset = (int)pBuf[3] & 0xFF; - - SK_MEMCPY(Buf, pBuf + 4, Offset); - Buf[Offset] = 0; - - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - /* Write the new entry or modify an existing one */ - Ret = VpdWrite(pAC, IoC, KeyStr, Buf); - if (Ret == SK_PNMI_VPD_NOWRITE ) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - else if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR025, - SK_PNMI_ERR025MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform an update of the VPD data. This is - * not mandantory, but just to be sure. - */ - Ret = VpdUpdate(pAC, IoC); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR026, - SK_PNMI_ERR026MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case SK_PNMI_VPD_DELETE: - /* Check if the buffer size is plausible */ - if (*pLen < 3) { - - *pLen = 3; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen > 3) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - KeyStr[0] = pBuf[1]; - KeyStr[1] = pBuf[2]; - KeyStr[2] = 0; - - /* Find the passed key in the array */ - for (Index = 0; Index < KeyNo; Index ++) { - - if (SK_STRCMP(KeyStr, KeyArr[Index]) == 0) { - - break; - } - } - /* - * If we cannot find the key it is wrong, so we - * return an appropriate error value. - */ - if (Index == KeyNo) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - /* Ok, you wanted it and you will get it */ - Ret = VpdDelete(pAC, IoC, KeyStr); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR027, - SK_PNMI_ERR027MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform an update of the VPD data. This is - * not mandantory, but just to be sure. - */ - Ret = VpdUpdate(pAC, IoC); - if (Ret != SK_PNMI_VPD_OK) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR028, - SK_PNMI_ERR028MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * General - OID handler function of various single instance OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int General( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int Index; - unsigned int Len; - unsigned int Offset; - unsigned int Val; - SK_U8 Val8; - SK_U16 Val16; - SK_U32 Val32; - SK_U64 Val64; - SK_U64 Val64RxHwErrs = 0; - SK_U64 Val64TxHwErrs = 0; - SK_BOOL Is64BitReq = SK_FALSE; - char Buf[256]; - int MacType; - - /* - * Check instance. We only handle single instance variables. - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Check action. We only allow get requests. - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - MacType = pAC->GIni.GIMacType; - - /* - * Check length for the various supported OIDs - */ - switch (Id) { - - case OID_GEN_XMIT_ERROR: - case OID_GEN_RCV_ERROR: - case OID_GEN_RCV_NO_BUFFER: -#ifndef SK_NDIS_64BIT_CTR - if (*pLen < sizeof(SK_U32)) { - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - -#else /* SK_NDIS_64BIT_CTR */ - - /* - * for compatibility, at least 32bit are required for oid - */ - if (*pLen < sizeof(SK_U32)) { - /* - * but indicate handling for 64bit values, - * if insufficient space is provided - */ - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - - Is64BitReq = (*pLen < sizeof(SK_U64)) ? SK_FALSE : SK_TRUE; -#endif /* SK_NDIS_64BIT_CTR */ - break; - - case OID_SKGE_PORT_NUMBER: - case OID_SKGE_DEVICE_TYPE: - case OID_SKGE_RESULT: - case OID_SKGE_RLMT_MONITOR_NUMBER: - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - case OID_SKGE_TRAP_NUMBER: - case OID_SKGE_MDB_VERSION: - case OID_SKGE_BOARDLEVEL: - case OID_SKGE_CHIPID: - case OID_SKGE_RAMSIZE: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_CHIPSET: - if (*pLen < sizeof(SK_U16)) { - - *pLen = sizeof(SK_U16); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_BUS_TYPE: - case OID_SKGE_BUS_SPEED: - case OID_SKGE_BUS_WIDTH: - case OID_SKGE_SENSOR_NUMBER: - case OID_SKGE_CHKSM_NUMBER: - case OID_SKGE_VAUXAVAIL: - if (*pLen < sizeof(SK_U8)) { - - *pLen = sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_TX_SW_QUEUE_LEN: - case OID_SKGE_TX_SW_QUEUE_MAX: - case OID_SKGE_TX_RETRY: - case OID_SKGE_RX_INTR_CTS: - case OID_SKGE_TX_INTR_CTS: - case OID_SKGE_RX_NO_BUF_CTS: - case OID_SKGE_TX_NO_BUF_CTS: - case OID_SKGE_TX_USED_DESCR_NO: - case OID_SKGE_RX_DELIVERED_CTS: - case OID_SKGE_RX_OCTETS_DELIV_CTS: - case OID_SKGE_RX_HW_ERROR_CTS: - case OID_SKGE_TX_HW_ERROR_CTS: - case OID_SKGE_IN_ERRORS_CTS: - case OID_SKGE_OUT_ERROR_CTS: - case OID_SKGE_ERR_RECOVERY_CTS: - case OID_SKGE_SYSUPTIME: - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - /* Checked later */ - break; - } - - /* Update statistic */ - if (Id == OID_SKGE_RX_HW_ERROR_CTS || - Id == OID_SKGE_TX_HW_ERROR_CTS || - Id == OID_SKGE_IN_ERRORS_CTS || - Id == OID_SKGE_OUT_ERROR_CTS || - Id == OID_GEN_XMIT_ERROR || - Id == OID_GEN_RCV_ERROR) { - - /* Force the XMAC to update its statistic counters and - * Increment semaphore to indicate that an update was - * already done. - */ - Ret = MacUpdate(pAC, IoC, 0, pAC->GIni.GIMacsFound - 1); - if (Ret != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.MacUpdatedFlag ++; - - /* - * Some OIDs consist of multiple hardware counters. Those - * values which are contained in all of them will be added - * now. - */ - switch (Id) { - - case OID_SKGE_RX_HW_ERROR_CTS: - case OID_SKGE_IN_ERRORS_CTS: - case OID_GEN_RCV_ERROR: - Val64RxHwErrs = - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_MISSED, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FRAMING, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_OVERFLOW, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_JABBER, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CARRIER, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_IRLENGTH, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SYMBOL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_SHORTS, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_RUNT, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_TOO_LONG, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_FCS, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HRX_CEXT, NetIndex); - break; - - case OID_SKGE_TX_HW_ERROR_CTS: - case OID_SKGE_OUT_ERROR_CTS: - case OID_GEN_XMIT_ERROR: - Val64TxHwErrs = - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_EXCESS_COL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_LATE_COL, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_UNDERRUN, NetIndex) + - GetStatVal(pAC, IoC, 0, SK_PNMI_HTX_CARRIER, NetIndex); - break; - } - } - - /* - * Retrieve value - */ - switch (Id) { - - case OID_SKGE_SUPPORTED_LIST: - Len = ID_TABLE_SIZE * sizeof(SK_U32); - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - for (Offset = 0, Index = 0; Offset < Len; - Offset += sizeof(SK_U32), Index ++) { - - Val32 = (SK_U32)IdTable[Index].Id; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - } - *pLen = Len; - break; - - case OID_SKGE_BOARDLEVEL: - Val32 = (SK_U32)pAC->GIni.GILevel; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_PORT_NUMBER: - Val32 = (SK_U32)pAC->GIni.GIMacsFound; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_DEVICE_TYPE: - Val32 = (SK_U32)pAC->Pnmi.DeviceType; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_DRIVER_DESCR: - if (pAC->Pnmi.pDriverDescription == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR007, - SK_PNMI_ERR007MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverDescription) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR029, - SK_PNMI_ERR029MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverDescription, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_DRIVER_VERSION: - if (pAC->Pnmi.pDriverVersion == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, - SK_PNMI_ERR030MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverVersion) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, - SK_PNMI_ERR031MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverVersion, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_DRIVER_RELDATE: - if (pAC->Pnmi.pDriverReleaseDate == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, - SK_PNMI_ERR053MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverReleaseDate) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, - SK_PNMI_ERR054MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverReleaseDate, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_DRIVER_FILENAME: - if (pAC->Pnmi.pDriverFileName == NULL) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR030, - SK_PNMI_ERR055MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - Len = SK_STRLEN(pAC->Pnmi.pDriverFileName) + 1; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR031, - SK_PNMI_ERR056MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, pAC->Pnmi.pDriverFileName, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_HW_DESCR: - /* - * The hardware description is located in the VPD. This - * query may move to the initialisation routine. But - * the VPD data is cached and therefore a call here - * will not make much difference. - */ - Len = 256; - if (VpdRead(pAC, IoC, VPD_NAME, Buf, (int *)&Len) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR032, - SK_PNMI_ERR032MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - Len ++; - if (Len > SK_PNMI_STRINGLEN1) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR033, - SK_PNMI_ERR033MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - *pBuf = (char)(Len - 1); - SK_MEMCPY(pBuf + 1, Buf, Len - 1); - *pLen = Len; - break; - - case OID_SKGE_HW_VERSION: - /* Oh, I love to do some string manipulation */ - if (*pLen < 5) { - - *pLen = 5; - return (SK_PNMI_ERR_TOO_SHORT); - } - Val8 = (SK_U8)pAC->GIni.GIPciHwRev; - pBuf[0] = 4; - pBuf[1] = 'v'; - pBuf[2] = (char)(0x30 | ((Val8 >> 4) & 0x0F)); - pBuf[3] = '.'; - pBuf[4] = (char)(0x30 | (Val8 & 0x0F)); - *pLen = 5; - break; - - case OID_SKGE_CHIPSET: - Val16 = pAC->Pnmi.Chipset; - SK_PNMI_STORE_U16(pBuf, Val16); - *pLen = sizeof(SK_U16); - break; - - case OID_SKGE_CHIPID: - Val32 = pAC->GIni.GIChipId; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_RAMSIZE: - Val32 = pAC->GIni.GIRamSize; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_VAUXAVAIL: - *pBuf = (char) pAC->GIni.GIVauxAvail; - *pLen = sizeof(char); - break; - - case OID_SKGE_BUS_TYPE: - *pBuf = (char) SK_PNMI_BUS_PCI; - *pLen = sizeof(char); - break; - - case OID_SKGE_BUS_SPEED: - *pBuf = pAC->Pnmi.PciBusSpeed; - *pLen = sizeof(char); - break; - - case OID_SKGE_BUS_WIDTH: - *pBuf = pAC->Pnmi.PciBusWidth; - *pLen = sizeof(char); - break; - - case OID_SKGE_RESULT: - Val32 = pAC->Pnmi.TestResult; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_SENSOR_NUMBER: - *pBuf = (char)pAC->I2c.MaxSens; - *pLen = sizeof(char); - break; - - case OID_SKGE_CHKSM_NUMBER: - *pBuf = SKCS_NUM_PROTOCOLS; - *pLen = sizeof(char); - break; - - case OID_SKGE_TRAP_NUMBER: - GetTrapQueueLen(pAC, &Len, &Val); - Val32 = (SK_U32)Val; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_TRAP: - GetTrapQueueLen(pAC, &Len, &Val); - if (*pLen < Len) { - - *pLen = Len; - return (SK_PNMI_ERR_TOO_SHORT); - } - CopyTrapQueue(pAC, pBuf); - *pLen = Len; - break; - - case OID_SKGE_RLMT_MONITOR_NUMBER: -/* XXX Not yet implemented by RLMT therefore we return zero elements */ - Val32 = 0; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_TX_SW_QUEUE_LEN: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueLen; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxSwQueueLen + - pAC->Pnmi.BufPort[1].TxSwQueueLen; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueLen; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxSwQueueLen + - pAC->Pnmi.Port[1].TxSwQueueLen; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - - case OID_SKGE_TX_SW_QUEUE_MAX: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxSwQueueMax; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxSwQueueMax + - pAC->Pnmi.BufPort[1].TxSwQueueMax; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxSwQueueMax; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxSwQueueMax + - pAC->Pnmi.Port[1].TxSwQueueMax; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_RETRY: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxRetryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxRetryCts + - pAC->Pnmi.BufPort[1].TxRetryCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxRetryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxRetryCts + - pAC->Pnmi.Port[1].TxRetryCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_INTR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxIntrCts + - pAC->Pnmi.BufPort[1].RxIntrCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxIntrCts + - pAC->Pnmi.Port[1].RxIntrCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_INTR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxIntrCts + - pAC->Pnmi.BufPort[1].TxIntrCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxIntrCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxIntrCts + - pAC->Pnmi.Port[1].TxIntrCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_NO_BUF_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxNoBufCts + - pAC->Pnmi.BufPort[1].RxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxNoBufCts + - pAC->Pnmi.Port[1].RxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_NO_BUF_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxNoBufCts + - pAC->Pnmi.BufPort[1].TxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxNoBufCts + - pAC->Pnmi.Port[1].TxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_USED_DESCR_NO: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].TxUsedDescrNo; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].TxUsedDescrNo + - pAC->Pnmi.BufPort[1].TxUsedDescrNo; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].TxUsedDescrNo; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].TxUsedDescrNo + - pAC->Pnmi.Port[1].TxUsedDescrNo; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_DELIVERED_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxDeliveredCts + - pAC->Pnmi.BufPort[1].RxDeliveredCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxDeliveredCts + - pAC->Pnmi.Port[1].RxDeliveredCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_OCTETS_DELIV_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxOctetsDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].RxOctetsDeliveredCts + - pAC->Pnmi.BufPort[1].RxOctetsDeliveredCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].RxOctetsDeliveredCts + - pAC->Pnmi.Port[1].RxOctetsDeliveredCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RX_HW_ERROR_CTS: - SK_PNMI_STORE_U64(pBuf, Val64RxHwErrs); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_TX_HW_ERROR_CTS: - SK_PNMI_STORE_U64(pBuf, Val64TxHwErrs); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_IN_ERRORS_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64RxHwErrs + - pAC->Pnmi.BufPort[0].RxNoBufCts + - pAC->Pnmi.BufPort[1].RxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64RxHwErrs + - pAC->Pnmi.Port[0].RxNoBufCts + - pAC->Pnmi.Port[1].RxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_OUT_ERROR_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64TxHwErrs + - pAC->Pnmi.BufPort[0].TxNoBufCts + - pAC->Pnmi.BufPort[1].TxNoBufCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - /* Single net mode */ - else { - Val64 = Val64TxHwErrs + - pAC->Pnmi.Port[0].TxNoBufCts + - pAC->Pnmi.Port[1].TxNoBufCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_ERR_RECOVERY_CTS: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.BufPort[NetIndex].ErrRecoveryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.BufPort[0].ErrRecoveryCts + - pAC->Pnmi.BufPort[1].ErrRecoveryCts; - } - } - else { - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - Val64 = pAC->Pnmi.Port[NetIndex].ErrRecoveryCts; - } - /* Single net mode */ - else { - Val64 = pAC->Pnmi.Port[0].ErrRecoveryCts + - pAC->Pnmi.Port[1].ErrRecoveryCts; - } - } - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_SYSUPTIME: - Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - Val64 -= pAC->Pnmi.StartUpTime; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_MDB_VERSION: - Val32 = SK_PNMI_MDB_VERSION; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_GEN_RCV_ERROR: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = Val64RxHwErrs + pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - else { - Val64 = Val64RxHwErrs + pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_XMIT_ERROR: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = Val64TxHwErrs + pAC->Pnmi.BufPort[NetIndex].TxNoBufCts; - } - else { - Val64 = Val64TxHwErrs + pAC->Pnmi.Port[NetIndex].TxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_RCV_NO_BUFFER: - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - Val64 = pAC->Pnmi.BufPort[NetIndex].RxNoBufCts; - } - else { - Val64 = pAC->Pnmi.Port[NetIndex].RxNoBufCts; - } - - /* - * by default 32bit values are evaluated - */ - if (!Is64BitReq) { - Val32 = (SK_U32)Val64; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - } - else { - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - } - break; - - case OID_GEN_TRANSMIT_QUEUE_LENGTH: - Val32 = (SK_U32)pAC->Pnmi.Port[NetIndex].TxSwQueueLen; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR034, - SK_PNMI_ERR034MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - if (Id == OID_SKGE_RX_HW_ERROR_CTS || - Id == OID_SKGE_TX_HW_ERROR_CTS || - Id == OID_SKGE_IN_ERRORS_CTS || - Id == OID_SKGE_OUT_ERROR_CTS || - Id == OID_GEN_XMIT_ERROR || - Id == OID_GEN_RCV_ERROR) { - - pAC->Pnmi.MacUpdatedFlag --; - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Rlmt - OID handler function of OID_SKGE_RLMT_XXX single instance. - * - * Description: - * Get/Presets/Sets the RLMT OIDs. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Rlmt( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - int Ret; - unsigned int PhysPortIndex; - unsigned int PhysPortMax; - SK_EVPARA EventParam; - SK_U32 Val32; - SK_U64 Val64; - - - /* - * Check instance. Only single instance OIDs are allowed here. - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Perform the requested action. - */ - if (Action == SK_PNMI_GET) { - - /* - * Check if the buffer length is large enough. - */ - - switch (Id) { - - case OID_SKGE_RLMT_MODE: - case OID_SKGE_RLMT_PORT_ACTIVE: - case OID_SKGE_RLMT_PORT_PREFERRED: - if (*pLen < sizeof(SK_U8)) { - - *pLen = sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_PORT_NUMBER: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_CHANGE_CTS: - case OID_SKGE_RLMT_CHANGE_TIME: - case OID_SKGE_RLMT_CHANGE_ESTIM: - case OID_SKGE_RLMT_CHANGE_THRES: - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR035, - SK_PNMI_ERR035MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Update RLMT statistic and increment semaphores to indicate - * that an update was already done. Maybe RLMT will hold its - * statistic always up to date some time. Then we can - * remove this type of call. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.RlmtUpdatedFlag ++; - - /* - * Retrieve Value - */ - switch (Id) { - - case OID_SKGE_RLMT_MODE: - *pBuf = (char)pAC->Rlmt.Net[0].RlmtMode; - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_PORT_NUMBER: - Val32 = (SK_U32)pAC->GIni.GIMacsFound; - SK_PNMI_STORE_U32(pBuf, Val32); - *pLen = sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_PORT_ACTIVE: - *pBuf = 0; - /* - * If multiple ports may become active this OID - * doesn't make sense any more. A new variable in - * the port structure should be created. However, - * for this variable the first active port is - * returned. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(PhysPortIndex); - break; - } - } - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_PORT_PREFERRED: - *pBuf = (char)SK_PNMI_PORT_PHYS2LOG(pAC->Rlmt.Net[NetIndex].Preference); - *pLen = sizeof(char); - break; - - case OID_SKGE_RLMT_CHANGE_CTS: - Val64 = pAC->Pnmi.RlmtChangeCts; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_TIME: - Val64 = pAC->Pnmi.RlmtChangeTime; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_ESTIM: - Val64 = pAC->Pnmi.RlmtChangeEstimate.Estimate; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_CHANGE_THRES: - Val64 = pAC->Pnmi.RlmtChangeThreshold; - SK_PNMI_STORE_U64(pBuf, Val64); - *pLen = sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("Rlmt: Unknown OID should be handled before")); - - pAC->Pnmi.RlmtUpdatedFlag --; - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - pAC->Pnmi.RlmtUpdatedFlag --; - } - else { - /* Perform a preset or set */ - switch (Id) { - - case OID_SKGE_RLMT_MODE: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(char)) { - - *pLen = sizeof(char); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Check if the value range is correct */ - if (*pLen != sizeof(char) || - (*pBuf & SK_PNMI_RLMT_MODE_CHK_LINK) == 0 || - *(SK_U8 *)pBuf > 15) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - /* Send an event to RLMT to change the mode */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] |= (SK_U32)(*pBuf); - EventParam.Para32[1] = 0; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR037, - SK_PNMI_ERR037MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case OID_SKGE_RLMT_PORT_PREFERRED: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(char)) { - - *pLen = sizeof(char); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Check if the value range is correct */ - if (*pLen != sizeof(char) || *(SK_U8 *)pBuf > - (SK_U8)pAC->GIni.GIMacsFound) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - - /* - * Send an event to RLMT change the preferred port. - * A param of -1 means automatic mode. RLMT will - * make the decision which is the preferred port. - */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = (SK_U32)(*pBuf) - 1; - EventParam.Para32[1] = NetIndex; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR038, - SK_PNMI_ERR038MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - break; - - case OID_SKGE_RLMT_CHANGE_THRES: - /* Check if the buffer length is plausible */ - if (*pLen < sizeof(SK_U64)) { - - *pLen = sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - /* - * There are not many restrictions to the - * value range. - */ - if (*pLen != sizeof(SK_U64)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - /* A preset ends here */ - if (Action == SK_PNMI_PRESET) { - - *pLen = 0; - return (SK_PNMI_ERR_OK); - } - /* - * Store the new threshold, which will be taken - * on the next timer event. - */ - SK_PNMI_READ_U64(pBuf, Val64); - pAC->Pnmi.RlmtChangeThreshold = Val64; - break; - - default: - /* The other OIDs are not be able for set */ - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * RlmtStat - OID handler function of OID_SKGE_RLMT_XXX multiple instance. - * - * Description: - * Performs get requests on multiple instance variables. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int RlmtStat( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - unsigned int Limit; - unsigned int Offset; - int Ret; - SK_U32 Val32; - SK_U64 Val64; - - /* - * Calculate the port indexes from the instance. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - - if ((Instance != (SK_U32)(-1))) { - /* Check instance range */ - if ((Instance < 1) || (Instance > PhysPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* Single net mode */ - PhysPortIndex = Instance - 1; - - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - } - - /* Both net modes */ - Limit = PhysPortIndex + 1; - } - else { - /* Single net mode */ - PhysPortIndex = 0; - Limit = PhysPortMax; - - /* Dual net mode */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - Limit = PhysPortIndex + 1; - } - } - - /* - * Currently only get requests are allowed. - */ - if (Action != SK_PNMI_GET) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Check if the buffer length is large enough. - */ - switch (Id) { - - case OID_SKGE_RLMT_PORT_INDEX: - case OID_SKGE_RLMT_STATUS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { - - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_RLMT_TX_HELLO_CTS: - case OID_SKGE_RLMT_RX_HELLO_CTS: - case OID_SKGE_RLMT_TX_SP_REQ_CTS: - case OID_SKGE_RLMT_RX_SP_CTS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U64)) { - - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U64); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR039, - SK_PNMI_ERR039MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - - } - - /* - * Update statistic and increment semaphores to indicate that - * an update was already done. - */ - if ((Ret = RlmtUpdate(pAC, IoC, NetIndex)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.RlmtUpdatedFlag ++; - - /* - * Get value - */ - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex ++) { - - switch (Id) { - - case OID_SKGE_RLMT_PORT_INDEX: - Val32 = PhysPortIndex; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_STATUS: - if (pAC->Rlmt.Port[PhysPortIndex].PortState == - SK_RLMT_PS_INIT || - pAC->Rlmt.Port[PhysPortIndex].PortState == - SK_RLMT_PS_DOWN) { - - Val32 = SK_PNMI_RLMT_STATUS_ERROR; - } - else if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - Val32 = SK_PNMI_RLMT_STATUS_ACTIVE; - } - else { - Val32 = SK_PNMI_RLMT_STATUS_STANDBY; - } - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_RLMT_TX_HELLO_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].TxHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_RX_HELLO_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].RxHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_TX_SP_REQ_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].TxSpHelloReqCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - case OID_SKGE_RLMT_RX_SP_CTS: - Val64 = pAC->Rlmt.Port[PhysPortIndex].RxSpHelloCts; - SK_PNMI_STORE_U64(pBuf + Offset, Val64); - Offset += sizeof(SK_U64); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("RlmtStat: Unknown OID should be errored before")); - - pAC->Pnmi.RlmtUpdatedFlag --; - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - - pAC->Pnmi.RlmtUpdatedFlag --; - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacPrivateConf - OID handler function of OIDs concerning the configuration - * - * Description: - * Get/Presets/Sets the OIDs concerning the configuration. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int MacPrivateConf( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - unsigned int LogPortMax; - unsigned int LogPortIndex; - unsigned int Limit; - unsigned int Offset; - char Val8; - char *pBufPtr; - int Ret; - SK_EVPARA EventParam; - SK_U32 Val32; - - /* - * Calculate instance if wished. MAC index 0 is the virtual MAC. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - LogPortMax--; - } - - if ((Instance != (SK_U32)(-1))) { /* Only one specific instance is queried */ - /* Check instance range */ - if ((Instance < 1) || (Instance > LogPortMax)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - LogPortIndex = SK_PNMI_PORT_INST2LOG(Instance); - Limit = LogPortIndex + 1; - } - - else { /* Instance == (SK_U32)(-1), get all Instances of that OID */ - - LogPortIndex = 0; - Limit = LogPortMax; - } - - /* - * Perform action - */ - if (Action == SK_PNMI_GET) { - - /* Check length */ - switch (Id) { - - case OID_SKGE_PMD: - case OID_SKGE_CONNECTOR: - case OID_SKGE_LINK_CAP: - case OID_SKGE_LINK_MODE: - case OID_SKGE_LINK_MODE_STATUS: - case OID_SKGE_LINK_STATUS: - case OID_SKGE_FLOWCTRL_CAP: - case OID_SKGE_FLOWCTRL_MODE: - case OID_SKGE_FLOWCTRL_STATUS: - case OID_SKGE_PHY_OPERATION_CAP: - case OID_SKGE_PHY_OPERATION_MODE: - case OID_SKGE_PHY_OPERATION_STATUS: - case OID_SKGE_SPEED_CAP: - case OID_SKGE_SPEED_MODE: - case OID_SKGE_SPEED_STATUS: - if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U8)) { - - *pLen = (Limit - LogPortIndex) * sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_MTU: - case OID_SKGE_PHY_TYPE: - if (*pLen < (Limit - LogPortIndex) * sizeof(SK_U32)) { - - *pLen = (Limit - LogPortIndex) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR041, - SK_PNMI_ERR041MSG); - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Update statistic and increment semaphore to indicate - * that an update was already done. - */ - if ((Ret = SirqUpdate(pAC, IoC)) != SK_PNMI_ERR_OK) { - - *pLen = 0; - return (Ret); - } - pAC->Pnmi.SirqUpdatedFlag ++; - - /* - * Get value - */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - pBufPtr = pBuf + Offset; - - switch (Id) { - - case OID_SKGE_PMD: - *pBufPtr = pAC->Pnmi.PMD; - Offset += sizeof(char); - break; - - case OID_SKGE_CONNECTOR: - *pBufPtr = pAC->Pnmi.Connector; - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_TYPE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - continue; - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - Val32 = pAC->GIni.GP[PhysPortIndex].PhyType; - SK_PNMI_STORE_U32(pBufPtr, Val32); - } - } - else { /* DualNetMode */ - - Val32 = pAC->GIni.GP[NetIndex].PhyType; - SK_PNMI_STORE_U32(pBufPtr, Val32); - } - Offset += sizeof(SK_U32); - break; - - case OID_SKGE_LINK_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkCap; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkCap; - } - Offset += sizeof(char); - break; - - case OID_SKGE_LINK_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkModeConf; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkModeConf; - } - Offset += sizeof(char); - break; - - case OID_SKGE_LINK_MODE_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = - CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); - } - } - else { /* DualNetMode */ - - *pBufPtr = CalculateLinkModeStatus(pAC, IoC, NetIndex); - } - Offset += sizeof(char); - break; - - case OID_SKGE_LINK_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = CalculateLinkStatus(pAC, IoC, PhysPortIndex); - } - } - else { /* DualNetMode */ - - *pBufPtr = CalculateLinkStatus(pAC, IoC, NetIndex); - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlCap; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlCap; - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlMode; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlMode; - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PFlowCtrlStatus; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PFlowCtrlStatus; - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSCap; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PMSCap; - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSMode; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PMSMode; - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PMSStatus; - } - } - else { - - *pBufPtr = pAC->GIni.GP[NetIndex].PMSStatus; - } - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_CAP: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical ports */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedCap; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedCap; - } - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_MODE: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeed; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeed; - } - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_STATUS: - if (!pAC->Pnmi.DualNetActiveFlag) { /* SingleNetMode */ - if (LogPortIndex == 0) { - /* Get value for virtual port */ - VirtualConf(pAC, IoC, Id, pBufPtr); - } - else { - /* Get value for physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - - *pBufPtr = pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed; - } - } - else { /* DualNetMode */ - - *pBufPtr = pAC->GIni.GP[NetIndex].PLinkSpeedUsed; - } - Offset += sizeof(char); - break; - - case OID_SKGE_MTU: - Val32 = SK_DRIVER_GET_MTU(pAC, IoC, NetIndex); - SK_PNMI_STORE_U32(pBufPtr, Val32); - Offset += sizeof(SK_U32); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("MacPrivateConf: Unknown OID should be handled before")); - - pAC->Pnmi.SirqUpdatedFlag --; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - pAC->Pnmi.SirqUpdatedFlag --; - - return (SK_PNMI_ERR_OK); - } - - /* - * From here SET or PRESET action. Check if the passed - * buffer length is plausible. - */ - switch (Id) { - - case OID_SKGE_LINK_MODE: - case OID_SKGE_FLOWCTRL_MODE: - case OID_SKGE_PHY_OPERATION_MODE: - case OID_SKGE_SPEED_MODE: - if (*pLen < Limit - LogPortIndex) { - - *pLen = Limit - LogPortIndex; - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen != Limit - LogPortIndex) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - case OID_SKGE_MTU: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - if (*pLen != sizeof(SK_U32)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* - * Perform preset or set - */ - Offset = 0; - for (; LogPortIndex < Limit; LogPortIndex ++) { - - switch (Id) { - - case OID_SKGE_LINK_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < SK_LMODE_HALF || - (LogPortIndex != 0 && Val8 > SK_LMODE_AUTOSENSE) || - (LogPortIndex == 0 && Val8 > SK_LMODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new link mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_LMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR043, - SK_PNMI_ERR043MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new link mode to - * the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, SK_HWEV_SET_LMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR043, - SK_PNMI_ERR043MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_FLOWCTRL_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < SK_FLOW_MODE_NONE || - (LogPortIndex != 0 && Val8 > SK_FLOW_MODE_SYM_OR_REM) || - (LogPortIndex == 0 && Val8 > SK_FLOW_MODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new flow control mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_FLOWMODE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR044, - SK_PNMI_ERR044MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new flow control - * mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_FLOWMODE, EventParam) - > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR044, - SK_PNMI_ERR044MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_PHY_OPERATION_MODE : - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - /* mode of this port remains unchanged */ - Offset += sizeof(char); - break; - } - if (Val8 < SK_MS_MODE_AUTO || - (LogPortIndex != 0 && Val8 > SK_MS_MODE_SLAVE) || - (LogPortIndex == 0 && Val8 > SK_MS_MODE_INDETERMINATED)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with new master/slave (role) mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex]. - ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_ROLE, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR042, - SK_PNMI_ERR042MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new master/slave - * (role) mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_ROLE, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR042, - SK_PNMI_ERR042MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - Offset += sizeof(char); - break; - - case OID_SKGE_SPEED_MODE: - /* Check the value range */ - Val8 = *(pBuf + Offset); - if (Val8 == 0) { - - Offset += sizeof(char); - break; - } - if (Val8 < (SK_LSPEED_AUTO) || - (LogPortIndex != 0 && Val8 > (SK_LSPEED_1000MBPS)) || - (LogPortIndex == 0 && Val8 > (SK_LSPEED_INDETERMINATED))) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - - return (SK_PNMI_ERR_OK); - } - - if (LogPortIndex == 0) { - - /* - * The virtual port consists of all currently - * active ports. Find them and send an event - * with the new flow control mode to SIRQ. - */ - for (PhysPortIndex = 0; - PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - continue; - } - - EventParam.Para32[0] = PhysPortIndex; - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_SPEED, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR045, - SK_PNMI_ERR045MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - } - else { - /* - * Send an event with the new flow control - * mode to the SIRQ module. - */ - EventParam.Para32[0] = SK_PNMI_PORT_LOG2PHYS( - pAC, LogPortIndex); - EventParam.Para32[1] = (SK_U32)Val8; - if (SkGeSirqEvent(pAC, IoC, - SK_HWEV_SET_SPEED, - EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, - SK_PNMI_ERR045, - SK_PNMI_ERR045MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - Offset += sizeof(char); - break; - - case OID_SKGE_MTU : - /* Check the value range */ - Val32 = *(SK_U32*)(pBuf + Offset); - if (Val32 == 0) { - /* mtu of this port remains unchanged */ - Offset += sizeof(SK_U32); - break; - } - if (SK_DRIVER_PRESET_MTU(pAC, IoC, NetIndex, Val32) != 0) { - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - /* The preset ends here */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - if (SK_DRIVER_SET_MTU(pAC, IoC, NetIndex, Val32) != 0) { - return (SK_PNMI_ERR_GENERAL); - } - - Offset += sizeof(SK_U32); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_PNMI, SK_DBGCAT_ERR, - ("MacPrivateConf: Unknown OID should be handled before set")); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * Monitor - OID handler function for RLMT_MONITOR_XXX - * - * Description: - * Because RLMT currently does not support the monitoring of - * remote adapter cards, we return always an empty table. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_BAD_VALUE The passed value is not in the valid - * value range. - * SK_PNMI_ERR_READ_ONLY The OID is read-only and cannot be set. - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -PNMI_STATIC int Monitor( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - unsigned int Index; - unsigned int Limit; - unsigned int Offset; - unsigned int Entries; - - - /* - * Calculate instance if wished. - */ - /* XXX Not yet implemented. Return always an empty table. */ - Entries = 0; - - if ((Instance != (SK_U32)(-1))) { - - if ((Instance < 1) || (Instance > Entries)) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - Index = (unsigned int)Instance - 1; - Limit = (unsigned int)Instance; - } - else { - Index = 0; - Limit = Entries; - } - - /* - * Get/Set value - */ - if (Action == SK_PNMI_GET) { - - for (Offset=0; Index < Limit; Index ++) { - - switch (Id) { - - case OID_SKGE_RLMT_MONITOR_INDEX: - case OID_SKGE_RLMT_MONITOR_ADDR: - case OID_SKGE_RLMT_MONITOR_ERRS: - case OID_SKGE_RLMT_MONITOR_TIMESTAMP: - case OID_SKGE_RLMT_MONITOR_ADMIN: - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR046, - SK_PNMI_ERR046MSG); - - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } - *pLen = Offset; - } - else { - /* Only MONITOR_ADMIN can be set */ - if (Id != OID_SKGE_RLMT_MONITOR_ADMIN) { - - *pLen = 0; - return (SK_PNMI_ERR_READ_ONLY); - } - - /* Check if the length is plausible */ - if (*pLen < (Limit - Index)) { - - return (SK_PNMI_ERR_TOO_SHORT); - } - /* Okay, we have a wide value range */ - if (*pLen != (Limit - Index)) { - - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } -/* - for (Offset=0; Index < Limit; Index ++) { - } -*/ -/* - * XXX Not yet implemented. Return always BAD_VALUE, because the table - * is empty. - */ - *pLen = 0; - return (SK_PNMI_ERR_BAD_VALUE); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * VirtualConf - Calculates the values of configuration OIDs for virtual port - * - * Description: - * We handle here the get of the configuration group OIDs, which are - * a little bit complicated. The virtual port consists of all currently - * active physical ports. If multiple ports are active and configured - * differently we get in some trouble to return a single value. So we - * get the value of the first active port and compare it with that of - * the other active ports. If they are not the same, we return a value - * that indicates that the state is indeterminated. - * - * Returns: - * Nothing - */ -PNMI_STATIC void VirtualConf( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf) /* Buffer used for the management data transfer */ -{ - unsigned int PhysPortMax; - unsigned int PhysPortIndex; - SK_U8 Val8; - SK_U32 Val32; - SK_BOOL PortActiveFlag; - SK_GEPORT *pPrt; - - *pBuf = 0; - PortActiveFlag = SK_FALSE; - PhysPortMax = pAC->GIni.GIMacsFound; - - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - - /* Check if the physical port is active */ - if (!pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - continue; - } - - PortActiveFlag = SK_TRUE; - - switch (Id) { - - case OID_SKGE_PHY_TYPE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - Val32 = pPrt->PhyType; - SK_PNMI_STORE_U32(pBuf, Val32); - continue; - } - - case OID_SKGE_LINK_CAP: - - /* - * Different capabilities should not happen, but - * in the case of the cases OR them all together. - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pPrt->PLinkCap; - break; - - case OID_SKGE_LINK_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PLinkModeConf; - continue; - } - - /* - * If we find an active port with a different link - * mode than the first one we return a value that - * indicates that the link mode is indeterminated. - */ - if (*pBuf != pPrt->PLinkModeConf) { - - *pBuf = SK_LMODE_INDETERMINATED; - } - break; - - case OID_SKGE_LINK_MODE_STATUS: - /* Get the link mode of the physical port */ - Val8 = CalculateLinkModeStatus(pAC, IoC, PhysPortIndex); - - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = Val8; - continue; - } - - /* - * If we find an active port with a different link - * mode status than the first one we return a value - * that indicates that the link mode status is - * indeterminated. - */ - if (*pBuf != Val8) { - - *pBuf = SK_LMODE_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_LINK_STATUS: - /* Get the link status of the physical port */ - Val8 = CalculateLinkStatus(pAC, IoC, PhysPortIndex); - - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = Val8; - continue; - } - - /* - * If we find an active port with a different link - * status than the first one, we return a value - * that indicates that the link status is - * indeterminated. - */ - if (*pBuf != Val8) { - - *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; - } - break; - - case OID_SKGE_FLOWCTRL_CAP: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PFlowCtrlCap; - continue; - } - - /* - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pPrt->PFlowCtrlCap; - break; - - case OID_SKGE_FLOWCTRL_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PFlowCtrlMode; - continue; - } - - /* - * If we find an active port with a different flow - * control mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pPrt->PFlowCtrlMode) { - - *pBuf = SK_FLOW_MODE_INDETERMINATED; - } - break; - - case OID_SKGE_FLOWCTRL_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PFlowCtrlStatus; - continue; - } - - /* - * If we find an active port with a different flow - * control status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pPrt->PFlowCtrlStatus) { - - *pBuf = SK_FLOW_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_PHY_OPERATION_CAP: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PMSCap; - continue; - } - - /* - * From a curious point of view the virtual port - * is capable of all found capabilities. - */ - *pBuf |= pPrt->PMSCap; - break; - - case OID_SKGE_PHY_OPERATION_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PMSMode; - continue; - } - - /* - * If we find an active port with a different master/ - * slave mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pPrt->PMSMode) { - - *pBuf = SK_MS_MODE_INDETERMINATED; - } - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PMSStatus; - continue; - } - - /* - * If we find an active port with a different master/ - * slave status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pPrt->PMSStatus) { - - *pBuf = SK_MS_STAT_INDETERMINATED; - } - break; - - case OID_SKGE_SPEED_MODE: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PLinkSpeed; - continue; - } - - /* - * If we find an active port with a different flow - * control mode than the first one, we return a value - * that indicates that the mode is indeterminated. - */ - if (*pBuf != pPrt->PLinkSpeed) { - - *pBuf = SK_LSPEED_INDETERMINATED; - } - break; - - case OID_SKGE_SPEED_STATUS: - /* Check if it is the first active port */ - if (*pBuf == 0) { - - *pBuf = pPrt->PLinkSpeedUsed; - continue; - } - - /* - * If we find an active port with a different flow - * control status than the first one, we return a - * value that indicates that the status is - * indeterminated. - */ - if (*pBuf != pPrt->PLinkSpeedUsed) { - - *pBuf = SK_LSPEED_STAT_INDETERMINATED; - } - break; - } - } - - /* - * If no port is active return an indeterminated answer - */ - if (!PortActiveFlag) { - - switch (Id) { - - case OID_SKGE_LINK_CAP: - *pBuf = SK_LMODE_CAP_INDETERMINATED; - break; - - case OID_SKGE_LINK_MODE: - *pBuf = SK_LMODE_INDETERMINATED; - break; - - case OID_SKGE_LINK_MODE_STATUS: - *pBuf = SK_LMODE_STAT_INDETERMINATED; - break; - - case OID_SKGE_LINK_STATUS: - *pBuf = SK_PNMI_RLMT_LSTAT_INDETERMINATED; - break; - - case OID_SKGE_FLOWCTRL_CAP: - case OID_SKGE_FLOWCTRL_MODE: - *pBuf = SK_FLOW_MODE_INDETERMINATED; - break; - - case OID_SKGE_FLOWCTRL_STATUS: - *pBuf = SK_FLOW_STAT_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_CAP: - *pBuf = SK_MS_CAP_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_MODE: - *pBuf = SK_MS_MODE_INDETERMINATED; - break; - - case OID_SKGE_PHY_OPERATION_STATUS: - *pBuf = SK_MS_STAT_INDETERMINATED; - break; - case OID_SKGE_SPEED_CAP: - *pBuf = SK_LSPEED_CAP_INDETERMINATED; - break; - - case OID_SKGE_SPEED_MODE: - *pBuf = SK_LSPEED_INDETERMINATED; - break; - - case OID_SKGE_SPEED_STATUS: - *pBuf = SK_LSPEED_STAT_INDETERMINATED; - break; - } - } -} - -/***************************************************************************** - * - * CalculateLinkStatus - Determins the link status of a physical port - * - * Description: - * Determins the link status the following way: - * LSTAT_PHY_DOWN: Link is down - * LSTAT_AUTONEG: Auto-negotiation failed - * LSTAT_LOG_DOWN: Link is up but RLMT did not yet put the port - * logically up. - * LSTAT_LOG_UP: RLMT marked the port as up - * - * Returns: - * Link status of physical port - */ -PNMI_STATIC SK_U8 CalculateLinkStatus( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex) /* Physical port index */ -{ - SK_U8 Result; - - if (!pAC->GIni.GP[PhysPortIndex].PHWLinkUp) { - - Result = SK_PNMI_RLMT_LSTAT_PHY_DOWN; - } - else if (pAC->GIni.GP[PhysPortIndex].PAutoNegFail > 0) { - - Result = SK_PNMI_RLMT_LSTAT_AUTONEG; - } - else if (!pAC->Rlmt.Port[PhysPortIndex].PortDown) { - - Result = SK_PNMI_RLMT_LSTAT_LOG_UP; - } - else { - Result = SK_PNMI_RLMT_LSTAT_LOG_DOWN; - } - - return (Result); -} - -/***************************************************************************** - * - * CalculateLinkModeStatus - Determins the link mode status of a phys. port - * - * Description: - * The COMMON module only tells us if the mode is half or full duplex. - * But in the decade of auto sensing it is useful for the user to - * know if the mode was negotiated or forced. Therefore we have a - * look to the mode, which was last used by the negotiation process. - * - * Returns: - * The link mode status - */ -PNMI_STATIC SK_U8 CalculateLinkModeStatus( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex) /* Physical port index */ -{ - SK_U8 Result; - - /* Get the current mode, which can be full or half duplex */ - Result = pAC->GIni.GP[PhysPortIndex].PLinkModeStatus; - - /* Check if no valid mode could be found (link is down) */ - if (Result < SK_LMODE_STAT_HALF) { - - Result = SK_LMODE_STAT_UNKNOWN; - } - else if (pAC->GIni.GP[PhysPortIndex].PLinkMode >= SK_LMODE_AUTOHALF) { - - /* - * Auto-negotiation was used to bring up the link. Change - * the already found duplex status that it indicates - * auto-negotiation was involved. - */ - if (Result == SK_LMODE_STAT_HALF) { - - Result = SK_LMODE_STAT_AUTOHALF; - } - else if (Result == SK_LMODE_STAT_FULL) { - - Result = SK_LMODE_STAT_AUTOFULL; - } - } - - return (Result); -} - -/***************************************************************************** - * - * GetVpdKeyArr - Obtain an array of VPD keys - * - * Description: - * Read the VPD keys and build an array of VPD keys, which are - * easy to access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int GetVpdKeyArr( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -char *pKeyArr, /* Ptr KeyArray */ -unsigned int KeyArrLen, /* Length of array in bytes */ -unsigned int *pKeyNo) /* Number of keys */ -{ - unsigned int BufKeysLen = SK_PNMI_VPD_BUFSIZE; - char BufKeys[SK_PNMI_VPD_BUFSIZE]; - unsigned int StartOffset; - unsigned int Offset; - int Index; - int Ret; - - - SK_MEMSET(pKeyArr, 0, KeyArrLen); - - /* - * Get VPD key list - */ - Ret = VpdKeys(pAC, IoC, (char *)&BufKeys, (int *)&BufKeysLen, - (int *)pKeyNo); - if (Ret > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR014, - SK_PNMI_ERR014MSG); - - return (SK_PNMI_ERR_GENERAL); - } - /* If no keys are available return now */ - if (*pKeyNo == 0 || BufKeysLen == 0) { - - return (SK_PNMI_ERR_OK); - } - /* - * If the key list is too long for us trunc it and give a - * errorlog notification. This case should not happen because - * the maximum number of keys is limited due to RAM limitations - */ - if (*pKeyNo > SK_PNMI_VPD_ENTRIES) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR015, - SK_PNMI_ERR015MSG); - - *pKeyNo = SK_PNMI_VPD_ENTRIES; - } - - /* - * Now build an array of fixed string length size and copy - * the keys together. - */ - for (Index = 0, StartOffset = 0, Offset = 0; Offset < BufKeysLen; - Offset ++) { - - if (BufKeys[Offset] != 0) { - - continue; - } - - if (Offset - StartOffset > SK_PNMI_VPD_KEY_SIZE) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR016, - SK_PNMI_ERR016MSG); - return (SK_PNMI_ERR_GENERAL); - } - - SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, - &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); - - Index ++; - StartOffset = Offset + 1; - } - - /* Last key not zero terminated? Get it anyway */ - if (StartOffset < Offset) { - - SK_STRNCPY(pKeyArr + Index * SK_PNMI_VPD_KEY_SIZE, - &BufKeys[StartOffset], SK_PNMI_VPD_KEY_SIZE); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * SirqUpdate - Let the SIRQ update its internal values - * - * Description: - * Just to be sure that the SIRQ module holds its internal data - * structures up to date, we send an update event before we make - * any access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int SirqUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC) /* IO context handle */ -{ - SK_EVPARA EventParam; - - - /* Was the module already updated during the current PNMI call? */ - if (pAC->Pnmi.SirqUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an synchronuous update event to the module */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - if (SkGeSirqEvent(pAC, IoC, SK_HWEV_UPDATE_STAT, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR047, - SK_PNMI_ERR047MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * RlmtUpdate - Let the RLMT update its internal values - * - * Description: - * Just to be sure that the RLMT module holds its internal data - * structures up to date, we send an update event before we make - * any access. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int RlmtUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - SK_EVPARA EventParam; - - - /* Was the module already updated during the current PNMI call? */ - if (pAC->Pnmi.RlmtUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an synchronuous update event to the module */ - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - if (SkRlmtEvent(pAC, IoC, SK_RLMT_STATS_UPDATE, EventParam) > 0) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR048, - SK_PNMI_ERR048MSG); - - return (SK_PNMI_ERR_GENERAL); - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * MacUpdate - Force the XMAC to output the current statistic - * - * Description: - * The XMAC holds its statistic internally. To obtain the current - * values we must send a command so that the statistic data will - * be written to a predefined memory area on the adapter. - * - * Returns: - * SK_PNMI_ERR_OK Task successfully performed. - * SK_PNMI_ERR_GENERAL Something went wrong. - */ -PNMI_STATIC int MacUpdate( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int FirstMac, /* Index of the first Mac to be updated */ -unsigned int LastMac) /* Index of the last Mac to be updated */ -{ - unsigned int MacIndex; - - /* - * Were the statistics already updated during the - * current PNMI call? - */ - if (pAC->Pnmi.MacUpdatedFlag > 0) { - - return (SK_PNMI_ERR_OK); - } - - /* Send an update command to all MACs specified */ - for (MacIndex = FirstMac; MacIndex <= LastMac; MacIndex ++) { - - /* - * 2002-09-13 pweber: Freeze the current SW counters. - * (That should be done as close as - * possible to the update of the - * HW counters) - */ - if (pAC->GIni.GIMacType == SK_MAC_XMAC) { - pAC->Pnmi.BufPort[MacIndex] = pAC->Pnmi.Port[MacIndex]; - } - - /* 2002-09-13 pweber: Update the HW counter */ - if (pAC->GIni.GIFunc.pFnMacUpdateStats(pAC, IoC, MacIndex) != 0) { - - return (SK_PNMI_ERR_GENERAL); - } - } - - return (SK_PNMI_ERR_OK); -} - -/***************************************************************************** - * - * GetStatVal - Retrieve an XMAC statistic counter - * - * Description: - * Retrieves the statistic counter of a virtual or physical port. The - * virtual port is identified by the index 0. It consists of all - * currently active ports. To obtain the counter value for this port - * we must add the statistic counter of all active ports. To grant - * continuous counter values for the virtual port even when port - * switches occur we must additionally add a delta value, which was - * calculated during a SK_PNMI_EVT_RLMT_ACTIVE_UP event. - * - * Returns: - * Requested statistic value - */ -PNMI_STATIC SK_U64 GetStatVal( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int LogPortIndex, /* Index of the logical Port to be processed */ -unsigned int StatIndex, /* Index to statistic value */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - unsigned int PhysPortIndex; - unsigned int PhysPortMax; - SK_U64 Val = 0; - - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { /* Dual net mode */ - - PhysPortIndex = NetIndex; - - Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); - } - else { /* Single Net mode */ - - if (LogPortIndex == 0) { - - PhysPortMax = pAC->GIni.GIMacsFound; - - /* Add counter of all active ports */ - for (PhysPortIndex = 0; PhysPortIndex < PhysPortMax; - PhysPortIndex ++) { - - if (pAC->Pnmi.Port[PhysPortIndex].ActiveFlag) { - - Val += GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); - } - } - - /* Correct value because of port switches */ - Val += pAC->Pnmi.VirtualCounterOffset[StatIndex]; - } - else { - /* Get counter value of physical port */ - PhysPortIndex = SK_PNMI_PORT_LOG2PHYS(pAC, LogPortIndex); - - Val = GetPhysStatVal(pAC, IoC, PhysPortIndex, StatIndex); - } - } - return (Val); -} - -/***************************************************************************** - * - * GetPhysStatVal - Get counter value for physical port - * - * Description: - * Builds a 64bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * in software by monitoring counter overflow interrupts in the - * event handler. To grant continous counter values during XMAC - * resets (caused by a workaround) we must add a delta value. - * The delta was calculated in the event handler when a - * SK_PNMI_EVT_XMAC_RESET was received. - * - * Returns: - * Counter value - */ -PNMI_STATIC SK_U64 GetPhysStatVal( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -unsigned int PhysPortIndex, /* Index of the logical Port to be processed */ -unsigned int StatIndex) /* Index to statistic value */ -{ - SK_U64 Val = 0; - SK_U32 LowVal = 0; - SK_U32 HighVal = 0; - SK_U16 Word; - int MacType; - unsigned int HelpIndex; - SK_GEPORT *pPrt; - - SK_PNMI_PORT *pPnmiPrt; - SK_GEMACFUNC *pFnMac; - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - - MacType = pAC->GIni.GIMacType; - - /* 2002-09-17 pweber: For XMAC, use the frozen SW counters (BufPort) */ - if (MacType == SK_MAC_XMAC) { - pPnmiPrt = &pAC->Pnmi.BufPort[PhysPortIndex]; - } - else { - pPnmiPrt = &pAC->Pnmi.Port[PhysPortIndex]; - } - - pFnMac = &pAC->GIni.GIFunc; - - switch (StatIndex) { - case SK_PNMI_HTX: - if (MacType == SK_MAC_GMAC) { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HTX_BROADCAST][MacType].Reg, - &LowVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HTX_MULTICAST][MacType].Reg, - &HighVal); - LowVal += HighVal; - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HTX_UNICAST][MacType].Reg, - &HighVal); - LowVal += HighVal; - } - else { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - } - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HRX: - if (MacType == SK_MAC_GMAC) { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HRX_BROADCAST][MacType].Reg, - &LowVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HRX_MULTICAST][MacType].Reg, - &HighVal); - LowVal += HighVal; - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[SK_PNMI_HRX_UNICAST][MacType].Reg, - &HighVal); - LowVal += HighVal; - } - else { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - } - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_OCTET: - case SK_PNMI_HRX_OCTET: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &HighVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex + 1][MacType].Reg, - &LowVal); - break; - - case SK_PNMI_HTX_BURST: - case SK_PNMI_HTX_EXCESS_DEF: - case SK_PNMI_HTX_CARRIER: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_MACC: - /* GMAC only supports PAUSE MAC control frames */ - if (MacType == SK_MAC_GMAC) { - HelpIndex = SK_PNMI_HTX_PMACC; - } - else { - HelpIndex = StatIndex; - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[HelpIndex][MacType].Reg, - &LowVal); - - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_COL: - case SK_PNMI_HRX_UNDERSIZE: - /* Not supported by XMAC */ - if (MacType == SK_MAC_XMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HTX_DEFFERAL: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - /* - * XMAC counts frames with deferred transmission - * even in full-duplex mode. - * - * In full-duplex mode the counter remains constant! - */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) || - (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL)) { - - LowVal = 0; - HighVal = 0; - } - else { - /* Otherwise get contents of hardware register */ - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - break; - - case SK_PNMI_HRX_BADOCTET: - /* Not supported by XMAC */ - if (MacType == SK_MAC_XMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &HighVal); - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex + 1][MacType].Reg, - &LowVal); - break; - - case SK_PNMI_HTX_OCTETLOW: - case SK_PNMI_HRX_OCTETLOW: - case SK_PNMI_HRX_BADOCTETLOW: - return (Val); - - case SK_PNMI_HRX_LONGFRAMES: - /* For XMAC the SW counter is managed by PNMI */ - if (MacType == SK_MAC_XMAC) { - return (pPnmiPrt->StatRxLongFrameCts); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HRX_TOO_LONG: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - - if (MacType == SK_MAC_GMAC) { - /* For GMAC the SW counter is additionally managed by PNMI */ - Val += pPnmiPrt->StatRxFrameTooLongCts; - } - else { - /* - * Frames longer than IEEE 802.3 frame max size are counted - * by XMAC in frame_too_long counter even reception of long - * frames was enabled and the frame was correct. - * So correct the value by subtracting RxLongFrame counter. - */ - Val -= pPnmiPrt->StatRxLongFrameCts; - } - - LowVal = (SK_U32)Val; - HighVal = (SK_U32)(Val >> 32); - break; - - case SK_PNMI_HRX_SHORTS: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - /* GM_RXE_FRAG?? */ - return (Val); - } - - /* - * XMAC counts short frame errors even if link down (#10620) - * - * If link-down the counter remains constant - */ - if (pPrt->PLinkModeStatus != SK_LMODE_STAT_UNKNOWN) { - - /* Otherwise get incremental difference */ - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - Val -= pPnmiPrt->RxShortZeroMark; - - LowVal = (SK_U32)Val; - HighVal = (SK_U32)(Val >> 32); - } - break; - - case SK_PNMI_HRX_MACC: - case SK_PNMI_HRX_MACC_UNKWN: - case SK_PNMI_HRX_BURST: - case SK_PNMI_HRX_MISSED: - case SK_PNMI_HRX_FRAMING: - case SK_PNMI_HRX_CARRIER: - case SK_PNMI_HRX_IRLENGTH: - case SK_PNMI_HRX_SYMBOL: - case SK_PNMI_HRX_CEXT: - /* Not supported by GMAC */ - if (MacType == SK_MAC_GMAC) { - return (Val); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - case SK_PNMI_HRX_PMACC_ERR: - /* For GMAC the SW counter is managed by PNMI */ - if (MacType == SK_MAC_GMAC) { - return (pPnmiPrt->StatRxPMaccErr); - } - - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - - /* SW counter managed by PNMI */ - case SK_PNMI_HTX_SYNC: - LowVal = (SK_U32)pPnmiPrt->StatSyncCts; - HighVal = (SK_U32)(pPnmiPrt->StatSyncCts >> 32); - break; - - /* SW counter managed by PNMI */ - case SK_PNMI_HTX_SYNC_OCTET: - LowVal = (SK_U32)pPnmiPrt->StatSyncOctetsCts; - HighVal = (SK_U32)(pPnmiPrt->StatSyncOctetsCts >> 32); - break; - - case SK_PNMI_HRX_FCS: - /* - * Broadcom filters FCS errors and counts it in - * Receive Error Counter register - */ - if (pPrt->PhyType == SK_PHY_BCOM) { - /* do not read while not initialized (PHY_READ hangs!)*/ - if (pPrt->PState != SK_PRT_RESET) { - SkXmPhyRead(pAC, IoC, PhysPortIndex, PHY_BCOM_RE_CTR, &Word); - - LowVal = Word; - } - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - else { - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - } - break; - - default: - (void)pFnMac->pFnMacStatistic(pAC, IoC, PhysPortIndex, - StatAddr[StatIndex][MacType].Reg, - &LowVal); - HighVal = pPnmiPrt->CounterHigh[StatIndex]; - break; - } - - Val = (((SK_U64)HighVal << 32) | (SK_U64)LowVal); - - /* Correct value because of possible XMAC reset. XMAC Errata #2 */ - Val += pPnmiPrt->CounterOffset[StatIndex]; - - return (Val); -} - -/***************************************************************************** - * - * ResetCounter - Set all counters and timestamps to zero - * - * Description: - * Notifies other common modules which store statistic data to - * reset their counters and finally reset our own counters. - * - * Returns: - * Nothing - */ -PNMI_STATIC void ResetCounter( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -SK_U32 NetIndex) -{ - unsigned int PhysPortIndex; - SK_EVPARA EventParam; - - - SK_MEMSET((char *)&EventParam, 0, sizeof(EventParam)); - - /* Notify sensor module */ - SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_CLEAR, EventParam); - - /* Notify RLMT module */ - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_STATS_CLEAR, EventParam); - EventParam.Para32[1] = 0; - - /* Notify SIRQ module */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_CLEAR_STAT, EventParam); - - /* Notify CSUM module */ -#ifdef SK_USE_CSUM - EventParam.Para32[0] = NetIndex; - EventParam.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_CSUM, SK_CSUM_EVENT_CLEAR_PROTO_STATS, - EventParam); -#endif /* SK_USE_CSUM */ - - /* Clear XMAC statistic */ - for (PhysPortIndex = 0; PhysPortIndex < - (unsigned int)pAC->GIni.GIMacsFound; PhysPortIndex ++) { - - (void)pAC->GIni.GIFunc.pFnMacResetCounter(pAC, IoC, PhysPortIndex); - - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].CounterHigh, - 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].CounterHigh)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - CounterOffset, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].CounterOffset)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex].StatSyncCts, - 0, sizeof(pAC->Pnmi.Port[PhysPortIndex].StatSyncCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatSyncOctetsCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatSyncOctetsCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxLongFrameCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxLongFrameCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxFrameTooLongCts, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxFrameTooLongCts)); - SK_MEMSET((char *)&pAC->Pnmi.Port[PhysPortIndex]. - StatRxPMaccErr, 0, sizeof(pAC->Pnmi.Port[ - PhysPortIndex].StatRxPMaccErr)); - } - - /* - * Clear local statistics - */ - SK_MEMSET((char *)&pAC->Pnmi.VirtualCounterOffset, 0, - sizeof(pAC->Pnmi.VirtualCounterOffset)); - pAC->Pnmi.RlmtChangeCts = 0; - pAC->Pnmi.RlmtChangeTime = 0; - SK_MEMSET((char *)&pAC->Pnmi.RlmtChangeEstimate.EstValue[0], 0, - sizeof(pAC->Pnmi.RlmtChangeEstimate.EstValue)); - pAC->Pnmi.RlmtChangeEstimate.EstValueIndex = 0; - pAC->Pnmi.RlmtChangeEstimate.Estimate = 0; - pAC->Pnmi.Port[NetIndex].TxSwQueueMax = 0; - pAC->Pnmi.Port[NetIndex].TxRetryCts = 0; - pAC->Pnmi.Port[NetIndex].RxIntrCts = 0; - pAC->Pnmi.Port[NetIndex].TxIntrCts = 0; - pAC->Pnmi.Port[NetIndex].RxNoBufCts = 0; - pAC->Pnmi.Port[NetIndex].TxNoBufCts = 0; - pAC->Pnmi.Port[NetIndex].TxUsedDescrNo = 0; - pAC->Pnmi.Port[NetIndex].RxDeliveredCts = 0; - pAC->Pnmi.Port[NetIndex].RxOctetsDeliveredCts = 0; - pAC->Pnmi.Port[NetIndex].ErrRecoveryCts = 0; -} - -/***************************************************************************** - * - * GetTrapEntry - Get an entry in the trap buffer - * - * Description: - * The trap buffer stores various events. A user application somehow - * gets notified that an event occured and retrieves the trap buffer - * contens (or simply polls the buffer). The buffer is organized as - * a ring which stores the newest traps at the beginning. The oldest - * traps are overwritten by the newest ones. Each trap entry has a - * unique number, so that applications may detect new trap entries. - * - * Returns: - * A pointer to the trap entry - */ -PNMI_STATIC char* GetTrapEntry( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* SNMP ID of the trap */ -unsigned int Size) /* Space needed for trap entry */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int BufFree = pAC->Pnmi.TrapBufFree; - unsigned int Beg = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - int Wrap; - unsigned int NeededSpace; - unsigned int EntrySize; - SK_U32 Val32; - SK_U64 Val64; - - - /* Last byte of entry will get a copy of the entry length */ - Size ++; - - /* - * Calculate needed buffer space */ - if (Beg >= Size) { - - NeededSpace = Size; - Wrap = SK_FALSE; - } - else { - NeededSpace = Beg + Size; - Wrap = SK_TRUE; - } - - /* - * Check if enough buffer space is provided. Otherwise - * free some entries. Leave one byte space between begin - * and end of buffer to make it possible to detect whether - * the buffer is full or empty - */ - while (BufFree < NeededSpace + 1) { - - if (End == 0) { - - End = SK_PNMI_TRAP_QUEUE_LEN; - } - - EntrySize = (unsigned int)*((unsigned char *)pBuf + End - 1); - BufFree += EntrySize; - End -= EntrySize; -#ifdef DEBUG - SK_MEMSET(pBuf + End, (char)(-1), EntrySize); -#endif /* DEBUG */ - if (End == BufPad) { -#ifdef DEBUG - SK_MEMSET(pBuf, (char)(-1), End); -#endif /* DEBUG */ - BufFree += End; - End = 0; - BufPad = 0; - } - } - - /* - * Insert new entry as first entry. Newest entries are - * stored at the beginning of the queue. - */ - if (Wrap) { - - BufPad = Beg; - Beg = SK_PNMI_TRAP_QUEUE_LEN - Size; - } - else { - Beg = Beg - Size; - } - BufFree -= NeededSpace; - - /* Save the current offsets */ - pAC->Pnmi.TrapQueueBeg = Beg; - pAC->Pnmi.TrapQueueEnd = End; - pAC->Pnmi.TrapBufPad = BufPad; - pAC->Pnmi.TrapBufFree = BufFree; - - /* Initialize the trap entry */ - *(pBuf + Beg + Size - 1) = (char)Size; - *(pBuf + Beg) = (char)Size; - Val32 = (pAC->Pnmi.TrapUnique) ++; - SK_PNMI_STORE_U32(pBuf + Beg + 1, Val32); - SK_PNMI_STORE_U32(pBuf + Beg + 1 + sizeof(SK_U32), TrapId); - Val64 = SK_PNMI_HUNDREDS_SEC(SkOsGetTime(pAC)); - SK_PNMI_STORE_U64(pBuf + Beg + 1 + 2 * sizeof(SK_U32), Val64); - - return (pBuf + Beg); -} - -/***************************************************************************** - * - * CopyTrapQueue - Copies the trap buffer for the TRAP OID - * - * Description: - * On a query of the TRAP OID the trap buffer contents will be - * copied continuously to the request buffer, which must be large - * enough. No length check is performed. - * - * Returns: - * Nothing - */ -PNMI_STATIC void CopyTrapQueue( -SK_AC *pAC, /* Pointer to adapter context */ -char *pDstBuf) /* Buffer to which the queued traps will be copied */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int Trap = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - unsigned int Len; - unsigned int DstOff = 0; - - - while (Trap != End) { - - Len = (unsigned int)*(pBuf + Trap); - - /* - * Last byte containing a copy of the length will - * not be copied. - */ - *(pDstBuf + DstOff) = (char)(Len - 1); - SK_MEMCPY(pDstBuf + DstOff + 1, pBuf + Trap + 1, Len - 2); - DstOff += Len - 1; - - Trap += Len; - if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { - - Trap = BufPad; - } - } -} - -/***************************************************************************** - * - * GetTrapQueueLen - Get the length of the trap buffer - * - * Description: - * Evaluates the number of currently stored traps and the needed - * buffer size to retrieve them. - * - * Returns: - * Nothing - */ -PNMI_STATIC void GetTrapQueueLen( -SK_AC *pAC, /* Pointer to adapter context */ -unsigned int *pLen, /* Length in Bytes of all queued traps */ -unsigned int *pEntries) /* Returns number of trapes stored in queue */ -{ - unsigned int BufPad = pAC->Pnmi.TrapBufPad; - unsigned int Trap = pAC->Pnmi.TrapQueueBeg; - unsigned int End = pAC->Pnmi.TrapQueueEnd; - char *pBuf = &pAC->Pnmi.TrapBuf[0]; - unsigned int Len; - unsigned int Entries = 0; - unsigned int TotalLen = 0; - - - while (Trap != End) { - - Len = (unsigned int)*(pBuf + Trap); - TotalLen += Len - 1; - Entries ++; - - Trap += Len; - if (Trap == SK_PNMI_TRAP_QUEUE_LEN) { - - Trap = BufPad; - } - } - - *pEntries = Entries; - *pLen = TotalLen; -} - -/***************************************************************************** - * - * QueueSimpleTrap - Store a simple trap to the trap buffer - * - * Description: - * A simple trap is a trap with now additional data. It consists - * simply of a trap code. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueSimpleTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId) /* Type of sensor trap */ -{ - GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_SIMPLE_LEN); -} - -/***************************************************************************** - * - * QueueSensorTrap - Stores a sensor trap in the trap buffer - * - * Description: - * Gets an entry in the trap buffer and fills it with sensor related - * data. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueSensorTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* Type of sensor trap */ -unsigned int SensorIndex) /* Index of sensor which caused the trap */ -{ - char *pBuf; - unsigned int Offset; - unsigned int DescrLen; - SK_U32 Val32; - - - /* Get trap buffer entry */ - DescrLen = SK_STRLEN(pAC->I2c.SenTable[SensorIndex].SenDesc); - pBuf = GetTrapEntry(pAC, TrapId, - SK_PNMI_TRAP_SENSOR_LEN_BASE + DescrLen); - Offset = SK_PNMI_TRAP_SIMPLE_LEN; - - /* Store additionally sensor trap related data */ - Val32 = OID_SKGE_SENSOR_INDEX; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 4; - Val32 = (SK_U32)SensorIndex; - SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); - Offset += 9; - - Val32 = (SK_U32)OID_SKGE_SENSOR_DESCR; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = (char)DescrLen; - SK_MEMCPY(pBuf + Offset + 5, pAC->I2c.SenTable[SensorIndex].SenDesc, - DescrLen); - Offset += DescrLen + 5; - - Val32 = OID_SKGE_SENSOR_TYPE; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 1; - *(pBuf + Offset + 5) = (char)pAC->I2c.SenTable[SensorIndex].SenType; - Offset += 6; - - Val32 = OID_SKGE_SENSOR_VALUE; - SK_PNMI_STORE_U32(pBuf + Offset, Val32); - *(pBuf + Offset + 4) = 4; - Val32 = (SK_U32)pAC->I2c.SenTable[SensorIndex].SenValue; - SK_PNMI_STORE_U32(pBuf + Offset + 5, Val32); -} - -/***************************************************************************** - * - * QueueRlmtNewMacTrap - Store a port switch trap in the trap buffer - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueRlmtNewMacTrap( -SK_AC *pAC, /* Pointer to adapter context */ -unsigned int ActiveMac) /* Index (0..n) of the currently active port */ -{ - char *pBuf; - SK_U32 Val32; - - - pBuf = GetTrapEntry(pAC, OID_SKGE_TRAP_RLMT_CHANGE_PORT, - SK_PNMI_TRAP_RLMT_CHANGE_LEN); - - Val32 = OID_SKGE_RLMT_PORT_ACTIVE; - SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)ActiveMac; -} - -/***************************************************************************** - * - * QueueRlmtPortTrap - Store port related RLMT trap to trap buffer - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void QueueRlmtPortTrap( -SK_AC *pAC, /* Pointer to adapter context */ -SK_U32 TrapId, /* Type of RLMT port trap */ -unsigned int PortIndex) /* Index of the port, which changed its state */ -{ - char *pBuf; - SK_U32 Val32; - - - pBuf = GetTrapEntry(pAC, TrapId, SK_PNMI_TRAP_RLMT_PORT_LEN); - - Val32 = OID_SKGE_RLMT_PORT_INDEX; - SK_PNMI_STORE_U32(pBuf + SK_PNMI_TRAP_SIMPLE_LEN, Val32); - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 4) = 1; - *(pBuf + SK_PNMI_TRAP_SIMPLE_LEN + 5) = (char)PortIndex; -} - -/***************************************************************************** - * - * CopyMac - Copies a MAC address - * - * Description: - * Nothing further to explain. - * - * Returns: - * Nothing - */ -PNMI_STATIC void CopyMac( -char *pDst, /* Pointer to destination buffer */ -SK_MAC_ADDR *pMac) /* Pointer of Source */ -{ - int i; - - - for (i = 0; i < sizeof(SK_MAC_ADDR); i ++) { - - *(pDst + i) = pMac->a[i]; - } -} - -#ifdef SK_POWER_MGMT -/***************************************************************************** - * - * PowerManagement - OID handler function of PowerManagement OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ - -PNMI_STATIC int PowerManagement( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* Get/PreSet/Set action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer to which to mgmt data will be retrieved */ -unsigned int *pLen, /* On call: buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode allways zero */ -{ - - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - - /* - * Check instance. We only handle single instance variables - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - - /* Check length */ - switch (Id) { - - case OID_PNP_CAPABILITIES: - if (*pLen < sizeof(SK_PNP_CAPABILITIES)) { - - *pLen = sizeof(SK_PNP_CAPABILITIES); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_SET_POWER: - case OID_PNP_QUERY_POWER: - if (*pLen < sizeof(SK_DEVICE_POWER_STATE)) - { - *pLen = sizeof(SK_DEVICE_POWER_STATE); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - if (*pLen < sizeof(SK_PM_PACKET_PATTERN)) { - - *pLen = sizeof(SK_PM_PACKET_PATTERN); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_PNP_ENABLE_WAKE_UP: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - } - - /* - * Perform action - */ - if (Action == SK_PNMI_GET) { - - /* - * Get value - */ - switch (Id) { - - case OID_PNP_CAPABILITIES: - RetCode = SkPowerQueryPnPCapabilities(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_QUERY_POWER: - /* The Windows DDK describes: An OID_PNP_QUERY_POWER requests - the miniport to indicate whether it can transition its NIC - to the low-power state. - A miniport driver must always return NDIS_STATUS_SUCCESS - to a query of OID_PNP_QUERY_POWER. */ - *pLen = sizeof(SK_DEVICE_POWER_STATE); - RetCode = SK_PNMI_ERR_OK; - break; - - /* NDIS handles these OIDs as write-only. - * So in case of get action the buffer with written length = 0 - * is returned - */ - case OID_PNP_SET_POWER: - case OID_PNP_ADD_WAKE_UP_PATTERN: - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - *pLen = 0; - RetCode = SK_PNMI_ERR_NOT_SUPPORTED; - break; - - case OID_PNP_ENABLE_WAKE_UP: - RetCode = SkPowerGetEnableWakeUp(pAC, IoC, pBuf, pLen); - break; - - default: - RetCode = SK_PNMI_ERR_GENERAL; - break; - } - - return (RetCode); - } - - - /* - * Perform preset or set - */ - - /* POWER module does not support PRESET action */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - switch (Id) { - case OID_PNP_SET_POWER: - RetCode = SkPowerSetPower(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_ADD_WAKE_UP_PATTERN: - RetCode = SkPowerAddWakeUpPattern(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_REMOVE_WAKE_UP_PATTERN: - RetCode = SkPowerRemoveWakeUpPattern(pAC, IoC, pBuf, pLen); - break; - - case OID_PNP_ENABLE_WAKE_UP: - RetCode = SkPowerSetEnableWakeUp(pAC, IoC, pBuf, pLen); - break; - - default: - RetCode = SK_PNMI_ERR_READ_ONLY; - } - - return (RetCode); -} -#endif /* SK_POWER_MGMT */ - -#ifdef SK_DIAG_SUPPORT -/***************************************************************************** - * - * DiagActions - OID handler function of Diagnostic driver - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ - -PNMI_STATIC int DiagActions( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (1..n) that is to be queried or -1 */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - - SK_U32 DiagStatus; - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - - /* - * Check instance. We only handle single instance variables. - */ - if (Instance != (SK_U32)(-1) && Instance != 1) { - - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - /* - * Check length. - */ - switch (Id) { - - case OID_SKGE_DIAG_MODE: - if (*pLen < sizeof(SK_U32)) { - - *pLen = sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SK_PNMI_ERR040, SK_PNMI_ERR040MSG); - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Perform action. */ - - /* GET value. */ - if (Action == SK_PNMI_GET) { - - switch (Id) { - - case OID_SKGE_DIAG_MODE: - DiagStatus = pAC->Pnmi.DiagAttached; - SK_PNMI_STORE_U32(pBuf, DiagStatus); - *pLen = sizeof(SK_U32); - RetCode = SK_PNMI_ERR_OK; - break; - - default: - *pLen = 0; - RetCode = SK_PNMI_ERR_GENERAL; - break; - } - return (RetCode); - } - - /* From here SET or PRESET value. */ - - /* PRESET value is not supported. */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - /* SET value. */ - switch (Id) { - case OID_SKGE_DIAG_MODE: - - /* Handle the SET. */ - switch (*pBuf) { - - /* Attach the DIAG to this adapter. */ - case SK_DIAG_ATTACHED: - /* Check if we come from running */ - if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { - - RetCode = SkDrvLeaveDiagMode(pAC); - - } - else if (pAC->Pnmi.DiagAttached == SK_DIAG_IDLE) { - - RetCode = SK_PNMI_ERR_OK; - } - - else { - - RetCode = SK_PNMI_ERR_GENERAL; - - } - - if (RetCode == SK_PNMI_ERR_OK) { - - pAC->Pnmi.DiagAttached = SK_DIAG_ATTACHED; - } - break; - - /* Enter the DIAG mode in the driver. */ - case SK_DIAG_RUNNING: - RetCode = SK_PNMI_ERR_OK; - - /* - * If DiagAttached is set, we can tell the driver - * to enter the DIAG mode. - */ - if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { - /* If DiagMode is not active, we can enter it. */ - if (!pAC->DiagModeActive) { - - RetCode = SkDrvEnterDiagMode(pAC); - } - else { - - RetCode = SK_PNMI_ERR_GENERAL; - } - } - else { - - RetCode = SK_PNMI_ERR_GENERAL; - } - - if (RetCode == SK_PNMI_ERR_OK) { - - pAC->Pnmi.DiagAttached = SK_DIAG_RUNNING; - } - break; - - case SK_DIAG_IDLE: - /* Check if we come from running */ - if (pAC->Pnmi.DiagAttached == SK_DIAG_RUNNING) { - - RetCode = SkDrvLeaveDiagMode(pAC); - - } - else if (pAC->Pnmi.DiagAttached == SK_DIAG_ATTACHED) { - - RetCode = SK_PNMI_ERR_OK; - } - - else { - - RetCode = SK_PNMI_ERR_GENERAL; - - } - - if (RetCode == SK_PNMI_ERR_OK) { - - pAC->Pnmi.DiagAttached = SK_DIAG_IDLE; - } - break; - - default: - RetCode = SK_PNMI_ERR_BAD_VALUE; - break; - } - break; - - default: - RetCode = SK_PNMI_ERR_GENERAL; - } - - if (RetCode == SK_PNMI_ERR_OK) { - *pLen = sizeof(SK_U32); - } - else { - - *pLen = 0; - } - return (RetCode); -} -#endif /* SK_DIAG_SUPPORT */ - -/***************************************************************************** - * - * Vct - OID handler function of OIDs - * - * Description: - * The code is simple. No description necessary. - * - * Returns: - * SK_PNMI_ERR_OK The request was performed successfully. - * SK_PNMI_ERR_GENERAL A general severe internal error occured. - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to contain - * the correct data (e.g. a 32bit value is - * needed, but a 16 bit value was passed). - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter). - * SK_PNMI_ERR_READ_ONLY Only the Get action is allowed. - * - */ - -PNMI_STATIC int Vct( -SK_AC *pAC, /* Pointer to adapter context */ -SK_IOC IoC, /* IO context handle */ -int Action, /* GET/PRESET/SET action */ -SK_U32 Id, /* Object ID that is to be processed */ -char *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* On call: pBuf buffer length. On return: used buffer */ -SK_U32 Instance, /* Instance (-1,2..n) that is to be queried */ -unsigned int TableIndex, /* Index to the Id table */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctBackupData; - SK_U32 LogPortMax; - SK_U32 PhysPortMax; - SK_U32 PhysPortIndex; - SK_U32 Limit; - SK_U32 Offset; - SK_BOOL Link; - SK_U32 RetCode = SK_PNMI_ERR_GENERAL; - int i; - SK_EVPARA Para; - SK_U32 CableLength; - - /* - * Calculate the port indexes from the instance. - */ - PhysPortMax = pAC->GIni.GIMacsFound; - LogPortMax = SK_PNMI_PORT_PHYS2LOG(PhysPortMax); - - /* Dual net mode? */ - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - LogPortMax--; - } - - if ((Instance != (SK_U32) (-1))) { - /* Check instance range. */ - if ((Instance < 2) || (Instance > LogPortMax)) { - *pLen = 0; - return (SK_PNMI_ERR_UNKNOWN_INST); - } - - if (pAC->Pnmi.DualNetActiveFlag == SK_TRUE) { - PhysPortIndex = NetIndex; - } - else { - PhysPortIndex = Instance - 2; - } - Limit = PhysPortIndex + 1; - } - else { - /* - * Instance == (SK_U32) (-1), get all Instances of that OID. - * - * Not implemented yet. May be used in future releases. - */ - PhysPortIndex = 0; - Limit = PhysPortMax; - } - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - if (pPrt->PHWLinkUp) { - Link = SK_TRUE; - } - else { - Link = SK_FALSE; - } - - /* Check MAC type */ - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Initialize backup data pointer. */ - pVctBackupData = &pAC->Pnmi.VctBackup[PhysPortIndex]; - - /* Check action type */ - if (Action == SK_PNMI_GET) { - /* Check length */ - switch (Id) { - - case OID_SKGE_VCT_GET: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_PNMI_VCT); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - case OID_SKGE_VCT_STATUS: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U8)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U8); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* Get value */ - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex++) { - switch (Id) { - - case OID_SKGE_VCT_GET: - if ((Link == SK_FALSE) && - (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING)) { - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 0) { - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] |= - (SK_PNMI_VCT_NEW_VCT_DATA | SK_PNMI_VCT_TEST_DONE); - - /* Copy results for later use to PNMI struct. */ - for (i = 0; i < 4; i++) { - if (pPrt->PMdiPairSts[i] == SK_PNMI_VCT_NORMAL_CABLE) { - if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] < 0xff)) { - pPrt->PMdiPairSts[i] = SK_PNMI_VCT_IMPEDANCE_MISMATCH; - } - } - if ((pPrt->PMdiPairLen[i] > 35) && (pPrt->PMdiPairLen[i] != 0xff)) { - CableLength = 1000 * (((175 * pPrt->PMdiPairLen[i]) / 210) - 28); - } - else { - CableLength = 0; - } - pVctBackupData->PMdiPairLen[i] = CableLength; - pVctBackupData->PMdiPairSts[i] = pPrt->PMdiPairSts[i]; - } - - Para.Para32[0] = PhysPortIndex; - Para.Para32[1] = -1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - SkEventDispatcher(pAC, IoC); - } - else { - ; /* VCT test is running. */ - } - } - - /* Get all results. */ - CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); - Offset += sizeof(SK_U8); - *(pBuf + Offset) = pPrt->PCableLen; - Offset += sizeof(SK_U8); - for (i = 0; i < 4; i++) { - SK_PNMI_STORE_U32((pBuf + Offset), pVctBackupData->PMdiPairLen[i]); - Offset += sizeof(SK_U32); - } - for (i = 0; i < 4; i++) { - *(pBuf + Offset) = pVctBackupData->PMdiPairSts[i]; - Offset += sizeof(SK_U8); - } - - RetCode = SK_PNMI_ERR_OK; - break; - - case OID_SKGE_VCT_STATUS: - CheckVctStatus(pAC, IoC, pBuf, Offset, PhysPortIndex); - Offset += sizeof(SK_U8); - RetCode = SK_PNMI_ERR_OK; - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } /* for */ - *pLen = Offset; - return (RetCode); - - } /* if SK_PNMI_GET */ - - /* - * From here SET or PRESET action. Check if the passed - * buffer length is plausible. - */ - - /* Check length */ - switch (Id) { - case OID_SKGE_VCT_SET: - if (*pLen < (Limit - PhysPortIndex) * sizeof(SK_U32)) { - *pLen = (Limit - PhysPortIndex) * sizeof(SK_U32); - return (SK_PNMI_ERR_TOO_SHORT); - } - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - - /* - * Perform preset or set. - */ - - /* VCT does not support PRESET action. */ - if (Action == SK_PNMI_PRESET) { - return (SK_PNMI_ERR_OK); - } - - Offset = 0; - for (; PhysPortIndex < Limit; PhysPortIndex++) { - switch (Id) { - case OID_SKGE_VCT_SET: /* Start VCT test. */ - if (Link == SK_FALSE) { - SkGeStopPort(pAC, IoC, PhysPortIndex, SK_STOP_ALL, SK_SOFT_RST); - - RetCode = SkGmCableDiagStatus(pAC, IoC, PhysPortIndex, SK_TRUE); - if (RetCode == 0) { /* RetCode: 0 => Start! */ - pAC->Pnmi.VctStatus[PhysPortIndex] |= SK_PNMI_VCT_PENDING; - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_NEW_VCT_DATA; - pAC->Pnmi.VctStatus[PhysPortIndex] &= ~SK_PNMI_VCT_LINK; - - /* - * Start VCT timer counter. - */ - SK_MEMSET((char *) &Para, 0, sizeof(Para)); - Para.Para32[0] = PhysPortIndex; - Para.Para32[1] = -1; - SkTimerStart(pAC, IoC, &pAC->Pnmi.VctTimeout[PhysPortIndex].VctTimer, - 4000000, SKGE_PNMI, SK_PNMI_EVT_VCT_RESET, Para); - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - else { /* RetCode: 2 => Running! */ - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - } - else { /* RetCode: 4 => Link! */ - RetCode = 4; - SK_PNMI_STORE_U32((pBuf + Offset), RetCode); - RetCode = SK_PNMI_ERR_OK; - } - Offset += sizeof(SK_U32); - break; - - default: - *pLen = 0; - return (SK_PNMI_ERR_GENERAL); - } - } /* for */ - *pLen = Offset; - return (RetCode); - -} /* Vct */ - - -PNMI_STATIC void CheckVctStatus( -SK_AC *pAC, -SK_IOC IoC, -char *pBuf, -SK_U32 Offset, -SK_U32 PhysPortIndex) -{ - SK_GEPORT *pPrt; - SK_PNMI_VCT *pVctData; - SK_U32 RetCode; - - pPrt = &pAC->GIni.GP[PhysPortIndex]; - - pVctData = (SK_PNMI_VCT *) (pBuf + Offset); - pVctData->VctStatus = SK_PNMI_VCT_NONE; - - if (!pPrt->PHWLinkUp) { - - /* Was a VCT test ever made before? */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { - if ((pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_LINK)) { - pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; - } - else { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; - } - } - - /* Check VCT test status. */ - RetCode = SkGmCableDiagStatus(pAC,IoC, PhysPortIndex, SK_FALSE); - if (RetCode == 2) { /* VCT test is running. */ - pVctData->VctStatus |= SK_PNMI_VCT_RUNNING; - } - else { /* VCT data was copied to pAC here. Check PENDING state. */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_PENDING) { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_VCT_DATA; - } - } - - if (pPrt->PCableLen != 0xff) { /* Old DSP value. */ - pVctData->VctStatus |= SK_PNMI_VCT_OLD_DSP_DATA; - } - } - else { - - /* Was a VCT test ever made before? */ - if (pAC->Pnmi.VctStatus[PhysPortIndex] & SK_PNMI_VCT_TEST_DONE) { - pVctData->VctStatus &= ~SK_PNMI_VCT_NEW_VCT_DATA; - pVctData->VctStatus |= SK_PNMI_VCT_OLD_VCT_DATA; - } - - /* DSP only valid in 100/1000 modes. */ - if (pAC->GIni.GP[PhysPortIndex].PLinkSpeedUsed != - SK_LSPEED_STAT_10MBPS) { - pVctData->VctStatus |= SK_PNMI_VCT_NEW_DSP_DATA; - } - } -} /* CheckVctStatus */ - - -/***************************************************************************** - * - * SkPnmiGenIoctl - Handles new generic PNMI IOCTL, calls the needed - * PNMI function depending on the subcommand and - * returns all data belonging to the complete database - * or OID request. - * - * Description: - * Looks up the requested subcommand, calls the corresponding handler - * function and passes all required parameters to it. - * The function is called by the driver. It is needed to handle the new - * generic PNMI IOCTL. This IOCTL is given to the driver and contains both - * the OID and a subcommand to decide what kind of request has to be done. - * - * Returns: - * SK_PNMI_ERR_OK The request was successfully performed - * SK_PNMI_ERR_GENERAL A general severe internal error occured - * SK_PNMI_ERR_TOO_SHORT The passed buffer is too short to take - * the data. - * SK_PNMI_ERR_UNKNOWN_OID The requested OID is unknown - * SK_PNMI_ERR_UNKNOWN_INST The requested instance of the OID doesn't - * exist (e.g. port instance 3 on a two port - * adapter. - */ -int SkPnmiGenIoctl( -SK_AC *pAC, /* Pointer to adapter context struct */ -SK_IOC IoC, /* I/O context */ -void *pBuf, /* Buffer used for the management data transfer */ -unsigned int *pLen, /* Length of buffer */ -SK_U32 NetIndex) /* NetIndex (0..n), in single net mode always zero */ -{ -SK_I32 Mode; /* Store value of subcommand. */ -SK_U32 Oid; /* Store value of OID. */ -int ReturnCode; /* Store return value to show status of PNMI action. */ -int HeaderLength; /* Length of desired action plus OID. */ - - ReturnCode = SK_PNMI_ERR_GENERAL; - - SK_MEMCPY(&Mode, pBuf, sizeof(SK_I32)); - SK_MEMCPY(&Oid, (char *) pBuf + sizeof(SK_I32), sizeof(SK_U32)); - HeaderLength = sizeof(SK_I32) + sizeof(SK_U32); - *pLen = *pLen - HeaderLength; - SK_MEMCPY((char *) pBuf + sizeof(SK_I32), (char *) pBuf + HeaderLength, *pLen); - - switch(Mode) { - case SK_GET_SINGLE_VAR: - ReturnCode = SkPnmiGetVar(pAC, IoC, Oid, - (char *) pBuf + sizeof(SK_I32), pLen, - ((SK_U32) (-1)), NetIndex); - SK_PNMI_STORE_U32(pBuf, ReturnCode); - *pLen = *pLen + sizeof(SK_I32); - break; - case SK_PRESET_SINGLE_VAR: - ReturnCode = SkPnmiPreSetVar(pAC, IoC, Oid, - (char *) pBuf + sizeof(SK_I32), pLen, - ((SK_U32) (-1)), NetIndex); - SK_PNMI_STORE_U32(pBuf, ReturnCode); - *pLen = *pLen + sizeof(SK_I32); - break; - case SK_SET_SINGLE_VAR: - ReturnCode = SkPnmiSetVar(pAC, IoC, Oid, - (char *) pBuf + sizeof(SK_I32), pLen, - ((SK_U32) (-1)), NetIndex); - SK_PNMI_STORE_U32(pBuf, ReturnCode); - *pLen = *pLen + sizeof(SK_I32); - break; - case SK_GET_FULL_MIB: - ReturnCode = SkPnmiGetStruct(pAC, IoC, pBuf, pLen, NetIndex); - break; - case SK_PRESET_FULL_MIB: - ReturnCode = SkPnmiPreSetStruct(pAC, IoC, pBuf, pLen, NetIndex); - break; - case SK_SET_FULL_MIB: - ReturnCode = SkPnmiSetStruct(pAC, IoC, pBuf, pLen, NetIndex); - break; - default: - break; - } - - return (ReturnCode); - -} /* SkGeIocGen */ diff --git a/drivers/net/sk98lin/skgesirq.c b/drivers/net/sk98lin/skgesirq.c deleted file mode 100644 index e5ee6d63ba4e..000000000000 --- a/drivers/net/sk98lin/skgesirq.c +++ /dev/null @@ -1,2229 +0,0 @@ -/****************************************************************************** - * - * Name: skgesirq.c - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.92 $ - * Date: $Date: 2003/09/16 14:37:07 $ - * Purpose: Special IRQ module - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * Special Interrupt handler - * - * The following abstract should show how this module is included - * in the driver path: - * - * In the ISR of the driver the bits for frame transmission complete and - * for receive complete are checked and handled by the driver itself. - * The bits of the slow path mask are checked after that and then the - * entry into the so-called "slow path" is prepared. It is an implementors - * decision whether this is executed directly or just scheduled by - * disabling the mask. In the interrupt service routine some events may be - * generated, so it would be a good idea to call the EventDispatcher - * right after this ISR. - * - * The Interrupt source register of the adapter is NOT read by this module. - * SO if the drivers implementor needs a while loop around the - * slow data paths interrupt bits, he needs to call the SkGeSirqIsr() for - * each loop entered. - * - * However, the MAC Interrupt status registers are read in a while loop. - * - */ - -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skgesirq.c,v 1.92 2003/09/16 14:37:07 rschmidt Exp $ (C) Marvell."; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#ifndef SK_SLIM -#include "h/skgepnmi.h" /* PNMI Definitions */ -#include "h/skrlmt.h" /* RLMT Definitions */ -#endif -#include "h/skdrv2nd.h" /* Adapter Control and Driver specific Def. */ - -/* local function prototypes */ -#ifdef GENESIS -static int SkGePortCheckUpXmac(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkGePortCheckUpBcom(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkPhyIsrBcom(SK_AC*, SK_IOC, int, SK_U16); -#endif /* GENESIS */ -#ifdef YUKON -static int SkGePortCheckUpGmac(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkPhyIsrGmac(SK_AC*, SK_IOC, int, SK_U16); -#endif /* YUKON */ -#ifdef OTHER_PHY -static int SkGePortCheckUpLone(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkGePortCheckUpNat(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkPhyIsrLone(SK_AC*, SK_IOC, int, SK_U16); -#endif /* OTHER_PHY */ - -#ifdef GENESIS -/* - * array of Rx counter from XMAC which are checked - * in AutoSense mode to check whether a link is not able to auto-negotiate. - */ -static const SK_U16 SkGeRxRegs[]= { - XM_RXF_64B, - XM_RXF_127B, - XM_RXF_255B, - XM_RXF_511B, - XM_RXF_1023B, - XM_RXF_MAX_SZ -} ; -#endif /* GENESIS */ - -#ifdef __C2MAN__ -/* - * Special IRQ function - * - * General Description: - * - */ -intro() -{} -#endif - -/****************************************************************************** - * - * SkHWInitDefSense() - Default Autosensing mode initialization - * - * Description: sets the PLinkMode for HWInit - * - * Returns: N/A - */ -static void SkHWInitDefSense( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != SK_LMODE_AUTOSENSE) { - pPrt->PLinkMode = pPrt->PLinkModeConf; - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoSensing: First mode %d on Port %d\n", - (int)SK_LMODE_AUTOFULL, Port)); - - pPrt->PLinkMode = (SK_U8)SK_LMODE_AUTOFULL; - - return; -} /* SkHWInitDefSense */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkHWSenseGetNext() - Get Next Autosensing Mode - * - * Description: gets the appropriate next mode - * - * Note: - * - */ -static SK_U8 SkHWSenseGetNext( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { - /* Leave all as configured */ - return(pPrt->PLinkModeConf); - } - - if (pPrt->PLinkMode == (SK_U8)SK_LMODE_AUTOFULL) { - /* Return next mode AUTOBOTH */ - return ((SK_U8)SK_LMODE_AUTOBOTH); - } - - /* Return default autofull */ - return ((SK_U8)SK_LMODE_AUTOFULL); -} /* SkHWSenseGetNext */ - - -/****************************************************************************** - * - * SkHWSenseSetNext() - Autosensing Set next mode - * - * Description: sets the appropriate next mode - * - * Returns: N/A - */ -static void SkHWSenseSetNext( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U8 NewMode) /* New Mode to be written in sense mode */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkModeConf != (SK_U8)SK_LMODE_AUTOSENSE) { - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoSensing: next mode %d on Port %d\n", - (int)NewMode, Port)); - - pPrt->PLinkMode = NewMode; - - return; -} /* SkHWSenseSetNext */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkHWLinkDown() - Link Down handling - * - * Description: handles the hardware link down signal - * - * Returns: N/A - */ -void SkHWLinkDown( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Disable all MAC interrupts */ - SkMacIrqDisable(pAC, IoC, Port); - - /* Disable Receiver and Transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - - /* Init default sense mode */ - SkHWInitDefSense(pAC, IoC, Port); - - if (pPrt->PHWLinkUp == SK_FALSE) { - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link down Port %d\n", Port)); - - /* Set Link to DOWN */ - pPrt->PHWLinkUp = SK_FALSE; - - /* Reset Port stati */ - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; - pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_INDETERMINATED; - - /* Re-init Phy especially when the AutoSense default is set now */ - SkMacInitPhy(pAC, IoC, Port, SK_FALSE); - - /* GP0: used for workaround of Rev. C Errata 2 */ - - /* Do NOT signal to RLMT */ - - /* Do NOT start the timer here */ -} /* SkHWLinkDown */ - - -/****************************************************************************** - * - * SkHWLinkUp() - Link Up handling - * - * Description: handles the hardware link up signal - * - * Returns: N/A - */ -static void SkHWLinkUp( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - /* We do NOT need to proceed on active link */ - return; - } - - pPrt->PHWLinkUp = SK_TRUE; - pPrt->PAutoNegFail = SK_FALSE; - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; - - if (pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOHALF && - pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOFULL && - pPrt->PLinkMode != (SK_U8)SK_LMODE_AUTOBOTH) { - /* Link is up and no Auto-negotiation should be done */ - - /* Link speed should be the configured one */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - /* default is 1000 Mbps */ - case SK_LSPEED_1000MBPS: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; - break; - case SK_LSPEED_100MBPS: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; - break; - case SK_LSPEED_10MBPS: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; - break; - } - - /* Set Link Mode Status */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_FULL; - } - else { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_HALF; - } - - /* No flow control without auto-negotiation */ - pPrt->PFlowCtrlStatus = (SK_U8)SK_FLOW_STAT_NONE; - - /* enable Rx/Tx */ - (void)SkMacRxTxEnable(pAC, IoC, Port); - } -} /* SkHWLinkUp */ - - -/****************************************************************************** - * - * SkMacParity() - MAC parity workaround - * - * Description: handles MAC parity errors correctly - * - * Returns: N/A - */ -static void SkMacParity( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index of the port failed */ -{ - SK_EVPARA Para; - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U32 TxMax; /* Tx Max Size Counter */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Clear IRQ Tx Parity Error */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_PERR); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), - (SK_U8)((pAC->GIni.GIChipId == CHIP_ID_YUKON && - pAC->GIni.GIChipRev == 0) ? GMF_CLI_TX_FC : GMF_CLI_TX_PE)); - } -#endif /* YUKON */ - - if (pPrt->PCheckPar) { - - if (Port == MAC_1) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E016, SKERR_SIRQ_E016MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E017, SKERR_SIRQ_E017MSG); - } - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - - Para.Para32[0] = Port; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - return; - } - - /* Check whether frames with a size of 1k were sent */ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, Port); - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXF_MAX_SZ, &TxMax); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - (void)SkGmMacStatistic(pAC, IoC, Port, GM_TXF_1518B, &TxMax); - } -#endif /* YUKON */ - - if (TxMax > 0) { - /* From now on check the parity */ - pPrt->PCheckPar = SK_TRUE; - } -} /* SkMacParity */ - - -/****************************************************************************** - * - * SkGeHwErr() - Hardware Error service routine - * - * Description: handles all HW Error interrupts - * - * Returns: N/A - */ -static void SkGeHwErr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -SK_U32 HwStatus) /* Interrupt status word */ -{ - SK_EVPARA Para; - SK_U16 Word; - - if ((HwStatus & (IS_IRQ_MST_ERR | IS_IRQ_STAT)) != 0) { - /* PCI Errors occured */ - if ((HwStatus & IS_IRQ_STAT) != 0) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E013, SKERR_SIRQ_E013MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E012, SKERR_SIRQ_E012MSG); - } - - /* Reset all bits in the PCI STATUS register */ - SK_IN16(IoC, PCI_C(PCI_STATUS), &Word); - - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_ON); - SK_OUT16(IoC, PCI_C(PCI_STATUS), (SK_U16)(Word | PCI_ERRBITS)); - SK_OUT8(IoC, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - if ((HwStatus & IS_NO_STAT_M1) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INSTAT); - } - - if ((HwStatus & IS_NO_STAT_M2) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INSTAT); - } - - if ((HwStatus & IS_NO_TIST_M1) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_1, RX_MFF_CTRL1), MFF_CLR_INTIST); - } - - if ((HwStatus & IS_NO_TIST_M2) != 0) { - /* Ignore it */ - /* This situation is also indicated in the descriptor */ - SK_OUT16(IoC, MR_ADDR(MAC_2, RX_MFF_CTRL1), MFF_CLR_INTIST); - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* This is necessary only for Rx timing measurements */ - if ((HwStatus & IS_IRQ_TIST_OV) != 0) { - /* increment Time Stamp Timer counter (high) */ - pAC->GIni.GITimeStampCnt++; - - /* Clear Time Stamp Timer IRQ */ - SK_OUT8(IoC, GMAC_TI_ST_CTRL, (SK_U8)GMT_ST_CLR_IRQ); - } - - if ((HwStatus & IS_IRQ_SENSOR) != 0) { - /* no sensors on 32-bit Yukon */ - if (pAC->GIni.GIYukon32Bit) { - /* disable HW Error IRQ */ - pAC->GIni.GIValIrqMask &= ~IS_HW_ERR; - } - } - } -#endif /* YUKON */ - - if ((HwStatus & IS_RAM_RD_PAR) != 0) { - SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_RD_PERR); - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E014, SKERR_SIRQ_E014MSG); - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - - if ((HwStatus & IS_RAM_WR_PAR) != 0) { - SK_OUT16(IoC, B3_RI_CTRL, RI_CLR_WR_PERR); - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E015, SKERR_SIRQ_E015MSG); - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_ADAP_FAIL, Para); - } - - if ((HwStatus & IS_M1_PAR_ERR) != 0) { - SkMacParity(pAC, IoC, MAC_1); - } - - if ((HwStatus & IS_M2_PAR_ERR) != 0) { - SkMacParity(pAC, IoC, MAC_2); - } - - if ((HwStatus & IS_R1_PAR_ERR) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_P); - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E018, SKERR_SIRQ_E018MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((HwStatus & IS_R2_PAR_ERR) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_P); - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E019, SKERR_SIRQ_E019MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } -} /* SkGeHwErr */ - - -/****************************************************************************** - * - * SkGeSirqIsr() - Special Interrupt Service Routine - * - * Description: handles all non data transfer specific interrupts (slow path) - * - * Returns: N/A - */ -void SkGeSirqIsr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -SK_U32 Istatus) /* Interrupt status word */ -{ - SK_EVPARA Para; - SK_U32 RegVal32; /* Read register value */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U16 PhyInt; - int i; - - if (((Istatus & IS_HW_ERR) & pAC->GIni.GIValIrqMask) != 0) { - /* read the HW Error Interrupt source */ - SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); - - SkGeHwErr(pAC, IoC, RegVal32); - } - - /* - * Packet Timeout interrupts - */ - /* Check whether MACs are correctly initialized */ - if (((Istatus & (IS_PA_TO_RX1 | IS_PA_TO_TX1)) != 0) && - pAC->GIni.GP[MAC_1].PState == SK_PRT_RESET) { - /* MAC 1 was not initialized but Packet timeout occured */ - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E004, - SKERR_SIRQ_E004MSG); - } - - if (((Istatus & (IS_PA_TO_RX2 | IS_PA_TO_TX2)) != 0) && - pAC->GIni.GP[MAC_2].PState == SK_PRT_RESET) { - /* MAC 2 was not initialized but Packet timeout occured */ - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E005, - SKERR_SIRQ_E005MSG); - } - - if ((Istatus & IS_PA_TO_RX1) != 0) { - /* Means network is filling us up */ - SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E002, - SKERR_SIRQ_E002MSG); - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX1); - } - - if ((Istatus & IS_PA_TO_RX2) != 0) { - /* Means network is filling us up */ - SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E003, - SKERR_SIRQ_E003MSG); - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_RX2); - } - - if ((Istatus & IS_PA_TO_TX1) != 0) { - - pPrt = &pAC->GIni.GP[0]; - - /* May be a normal situation in a server with a slow network */ - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX1); - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* - * workaround: if in half duplex mode, check for Tx hangup. - * Read number of TX'ed bytes, wait for 10 ms, then compare - * the number with current value. If nothing changed, we assume - * that Tx is hanging and do a FIFO flush (see event routine). - */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && - !pPrt->HalfDupTimerActive) { - /* - * many more pack. arb. timeouts may come in between, - * we ignore those - */ - pPrt->HalfDupTimerActive = SK_TRUE; - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, 0); - - (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_HI, &RegVal32); - - pPrt->LastOctets = (SK_U64)RegVal32 << 32; - - (void)SkXmMacStatistic(pAC, IoC, 0, XM_TXO_OK_LO, &RegVal32); - - pPrt->LastOctets += RegVal32; - - Para.Para32[0] = 0; - SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, - SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); - } - } -#endif /* GENESIS */ - } - - if ((Istatus & IS_PA_TO_TX2) != 0) { - - pPrt = &pAC->GIni.GP[1]; - - /* May be a normal situation in a server with a slow network */ - SK_OUT16(IoC, B3_PA_CTRL, PA_CLR_TO_TX2); - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* workaround: see above */ - if ((pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) && - !pPrt->HalfDupTimerActive) { - pPrt->HalfDupTimerActive = SK_TRUE; - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, 1); - - (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_HI, &RegVal32); - - pPrt->LastOctets = (SK_U64)RegVal32 << 32; - - (void)SkXmMacStatistic(pAC, IoC, 1, XM_TXO_OK_LO, &RegVal32); - - pPrt->LastOctets += RegVal32; - - Para.Para32[0] = 1; - SkTimerStart(pAC, IoC, &pPrt->HalfDupChkTimer, SK_HALFDUP_CHK_TIME, - SKGE_HWAC, SK_HWEV_HALFDUP_CHK, Para); - } - } -#endif /* GENESIS */ - } - - /* Check interrupts of the particular queues */ - if ((Istatus & IS_R1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E006, - SKERR_SIRQ_E006MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_R2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_R2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E007, - SKERR_SIRQ_E007MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XS1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XS1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E008, - SKERR_SIRQ_E008MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XA1_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XA1_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E009, - SKERR_SIRQ_E009MSG); - Para.Para64 = MAC_1; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_1; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XS2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XS2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E010, - SKERR_SIRQ_E010MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((Istatus & IS_XA2_C) != 0) { - /* Clear IRQ */ - SK_OUT32(IoC, B0_XA2_CSR, CSR_IRQ_CL_C); - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_SIRQ_E011, - SKERR_SIRQ_E011MSG); - Para.Para64 = MAC_2; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_FAIL, Para); - Para.Para32[0] = MAC_2; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - /* External reg interrupt */ - if ((Istatus & IS_EXT_REG) != 0) { - /* Test IRQs from PHY */ - for (i = 0; i < pAC->GIni.GIMacsFound; i++) { - - pPrt = &pAC->GIni.GP[i]; - - if (pPrt->PState == SK_PRT_RESET) { - continue; - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - switch (pPrt->PhyType) { - - case SK_PHY_XMAC: - break; - - case SK_PHY_BCOM: - SkXmPhyRead(pAC, IoC, i, PHY_BCOM_INT_STAT, &PhyInt); - - if ((PhyInt & ~PHY_B_DEF_MSK) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Bcom Int: 0x%04X\n", - i, PhyInt)); - SkPhyIsrBcom(pAC, IoC, i, PhyInt); - } - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyRead(pAC, IoC, i, PHY_LONE_INT_STAT, &PhyInt); - - if ((PhyInt & PHY_L_DEF_MSK) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Lone Int: %x\n", - i, PhyInt)); - SkPhyIsrLone(pAC, IoC, i, PhyInt); - } - break; -#endif /* OTHER_PHY */ - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* Read PHY Interrupt Status */ - SkGmPhyRead(pAC, IoC, i, PHY_MARV_INT_STAT, &PhyInt); - - if ((PhyInt & PHY_M_DEF_MSK) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Port %d Marv Int: 0x%04X\n", - i, PhyInt)); - SkPhyIsrGmac(pAC, IoC, i, PhyInt); - } - } -#endif /* YUKON */ - } - } - - /* I2C Ready interrupt */ - if ((Istatus & IS_I2C_READY) != 0) { -#ifdef SK_SLIM - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); -#else - SkI2cIsr(pAC, IoC); -#endif - } - - /* SW forced interrupt */ - if ((Istatus & IS_IRQ_SW) != 0) { - /* clear the software IRQ */ - SK_OUT8(IoC, B0_CTST, CS_CL_SW_IRQ); - } - - if ((Istatus & IS_LNK_SYNC_M1) != 0) { - /* - * We do NOT need the Link Sync interrupt, because it shows - * us only a link going down. - */ - /* clear interrupt */ - SK_OUT8(IoC, MR_ADDR(MAC_1, LNK_SYNC_CTRL), LED_CLR_IRQ); - } - - /* Check MAC after link sync counter */ - if ((Istatus & IS_MAC1) != 0) { - /* IRQ from MAC 1 */ - SkMacIrq(pAC, IoC, MAC_1); - } - - if ((Istatus & IS_LNK_SYNC_M2) != 0) { - /* - * We do NOT need the Link Sync interrupt, because it shows - * us only a link going down. - */ - /* clear interrupt */ - SK_OUT8(IoC, MR_ADDR(MAC_2, LNK_SYNC_CTRL), LED_CLR_IRQ); - } - - /* Check MAC after link sync counter */ - if ((Istatus & IS_MAC2) != 0) { - /* IRQ from MAC 2 */ - SkMacIrq(pAC, IoC, MAC_2); - } - - /* Timer interrupt (served last) */ - if ((Istatus & IS_TIMINT) != 0) { - /* check for HW Errors */ - if (((Istatus & IS_HW_ERR) & ~pAC->GIni.GIValIrqMask) != 0) { - /* read the HW Error Interrupt source */ - SK_IN32(IoC, B0_HWE_ISRC, &RegVal32); - - SkGeHwErr(pAC, IoC, RegVal32); - } - - SkHwtIsr(pAC, IoC); - } - -} /* SkGeSirqIsr */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkGePortCheckShorts() - Implementing XMAC Workaround Errata # 2 - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - */ -static int SkGePortCheckShorts( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_U32 Shorts; /* Short Event Counter */ - SK_U32 CheckShorts; /* Check value for Short Event Counter */ - SK_U64 RxCts; /* Rx Counter (packets on network) */ - SK_U32 RxTmp; /* Rx temp. Counter */ - SK_U32 FcsErrCts; /* FCS Error Counter */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Rtv; /* Return value */ - int i; - - pPrt = &pAC->GIni.GP[Port]; - - /* Default: no action */ - Rtv = SK_HW_PS_NONE; - - (void)SkXmUpdateStats(pAC, IoC, Port); - - /* Extra precaution: check for short Event counter */ - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); - - /* - * Read Rx counters (packets seen on the network and not necessarily - * really received. - */ - RxCts = 0; - - for (i = 0; i < ARRAY_SIZE(SkGeRxRegs); i++) { - - (void)SkXmMacStatistic(pAC, IoC, Port, SkGeRxRegs[i], &RxTmp); - - RxCts += (SK_U64)RxTmp; - } - - /* On default: check shorts against zero */ - CheckShorts = 0; - - /* Extra precaution on active links */ - if (pPrt->PHWLinkUp) { - /* Reset Link Restart counter */ - pPrt->PLinkResCt = 0; - pPrt->PAutoNegTOCt = 0; - - /* If link is up check for 2 */ - CheckShorts = 2; - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXF_FCS_ERR, &FcsErrCts); - - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg == SK_LIPA_UNKNOWN && - (pPrt->PLinkMode == SK_LMODE_HALF || - pPrt->PLinkMode == SK_LMODE_FULL)) { - /* - * This is autosensing and we are in the fallback - * manual full/half duplex mode. - */ - if (RxCts == pPrt->PPrevRx) { - /* Nothing received, restart link */ - pPrt->PPrevFcs = FcsErrCts; - pPrt->PPrevShorts = Shorts; - - return(SK_HW_PS_RESTART); - } - else { - pPrt->PLipaAutoNeg = SK_LIPA_MANUAL; - } - } - - if (((RxCts - pPrt->PPrevRx) > pPrt->PRxLim) || - (!(FcsErrCts - pPrt->PPrevFcs))) { - /* - * Note: The compare with zero above has to be done the way shown, - * otherwise the Linux driver will have a problem. - */ - /* - * We received a bunch of frames or no CRC error occured on the - * network -> ok. - */ - pPrt->PPrevRx = RxCts; - pPrt->PPrevFcs = FcsErrCts; - pPrt->PPrevShorts = Shorts; - - return(SK_HW_PS_NONE); - } - - pPrt->PPrevFcs = FcsErrCts; - } - - - if ((Shorts - pPrt->PPrevShorts) > CheckShorts) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Short Event Count Restart Port %d \n", Port)); - Rtv = SK_HW_PS_RESTART; - } - - pPrt->PPrevShorts = Shorts; - pPrt->PPrevRx = RxCts; - - return(Rtv); -} /* SkGePortCheckShorts */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkGePortCheckUp() - Check if the link is up - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port) /* Which port should be checked */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_BOOL AutoNeg; /* Is Auto-negotiation used ? */ - int Rtv; /* Return value */ - - Rtv = SK_HW_PS_NONE; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - switch (pPrt->PhyType) { - - case SK_PHY_XMAC: - Rtv = SkGePortCheckUpXmac(pAC, IoC, Port, AutoNeg); - break; - case SK_PHY_BCOM: - Rtv = SkGePortCheckUpBcom(pAC, IoC, Port, AutoNeg); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - Rtv = SkGePortCheckUpLone(pAC, IoC, Port, AutoNeg); - break; - case SK_PHY_NAT: - Rtv = SkGePortCheckUpNat(pAC, IoC, Port, AutoNeg); - break; -#endif /* OTHER_PHY */ - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - Rtv = SkGePortCheckUpGmac(pAC, IoC, Port, AutoNeg); - } -#endif /* YUKON */ - - return(Rtv); -} /* SkGePortCheckUp */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkGePortCheckUpXmac() - Implementing of the Workaround Errata # 2 - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpXmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - SK_U32 Shorts; /* Short Event Counter */ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U32 GpReg; /* General Purpose register value */ - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 IsrcSum; /* Interrupt source register sum */ - SK_U16 LpAb; /* Link Partner Ability */ - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 ExtStat; /* Extended Status Register */ - SK_U8 NextMode; /* Next AutoSensing Mode */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - if (pPrt->PhyType != SK_PHY_XMAC) { - return(SK_HW_PS_NONE); - } - else { - return(SkGePortCheckShorts(pAC, IoC, Port)); - } - } - - IsrcSum = pPrt->PIsave; - pPrt->PIsave = 0; - - /* Now wait for each port's link */ - if (pPrt->PLinkBroken) { - /* Link was broken */ - XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); - - if ((GpReg & XM_GP_INP_ASS) == 0) { - /* The Link is in sync */ - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); - - if ((Isrc & XM_IS_INP_ASS) == 0) { - /* It has been in sync since last time */ - /* Restart the PORT */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link in sync Restart Port %d\n", Port)); - - (void)SkXmUpdateStats(pAC, IoC, Port); - - /* We now need to reinitialize the PrevShorts counter */ - (void)SkXmMacStatistic(pAC, IoC, Port, XM_RXE_SHT_ERR, &Shorts); - pPrt->PPrevShorts = Shorts; - - pPrt->PLinkBroken = SK_FALSE; - - /* - * Link Restart Workaround: - * it may be possible that the other Link side - * restarts its link as well an we detect - * another LinkBroken. To prevent this - * happening we check for a maximum number - * of consecutive restart. If those happens, - * we do NOT restart the active link and - * check whether the link is now o.k. - */ - pPrt->PLinkResCt++; - - pPrt->PAutoNegTimeOut = 0; - - if (pPrt->PLinkResCt < SK_MAX_LRESTART) { - return(SK_HW_PS_RESTART); - } - - pPrt->PLinkResCt = 0; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Do NOT restart on Port %d %x %x\n", Port, Isrc, IsrcSum)); - } - else { - pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Save Sync/nosync Port %d %x %x\n", Port, Isrc, IsrcSum)); - - /* Do nothing more if link is broken */ - return(SK_HW_PS_NONE); - } - } - else { - /* Do nothing more if link is broken */ - return(SK_HW_PS_NONE); - } - - } - else { - /* Link was not broken, check if it is */ - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - if ((Isrc & XM_IS_INP_ASS) != 0) { - pPrt->PLinkBroken = SK_TRUE; - /* Re-Init Link partner Autoneg flag */ - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link broken Port %d\n", Port)); - - /* Cable removed-> reinit sense mode */ - SkHWInitDefSense(pAC, IoC, Port); - - return(SK_HW_PS_RESTART); - } - } - } - else { - SkXmAutoNegLipaXmac(pAC, IoC, Port, Isrc); - - if (SkGePortCheckShorts(pAC, IoC, Port) == SK_HW_PS_RESTART) { - return(SK_HW_PS_RESTART); - } - } - } - - /* - * here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - XM_IN32(IoC, Port, XM_GP_PORT, &GpReg); - XM_IN16(IoC, Port, XM_ISRC, &Isrc); - IsrcSum |= Isrc; - - SkXmAutoNegLipaXmac(pAC, IoC, Port, IsrcSum); - - if ((GpReg & XM_GP_INP_ASS) != 0 || (IsrcSum & XM_IS_INP_ASS) != 0) { - if ((GpReg & XM_GP_INP_ASS) == 0) { - /* Save Auto-negotiation Done interrupt only if link is in sync */ - pPrt->PIsave = (SK_U16)(IsrcSum & XM_IS_AND); - } -#ifdef DEBUG - if ((pPrt->PIsave & XM_IS_AND) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done rescheduled Port %d\n", Port)); - } -#endif /* DEBUG */ - return(SK_HW_PS_NONE); - } - - if (AutoNeg) { - if ((IsrcSum & XM_IS_AND) != 0) { - SkHWLinkUp(pAC, IoC, Port); - Done = SkMacAutoNegDone(pAC, IoC, Port); - if (Done != SK_AND_OK) { - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, ResAb %x)\n", - Port, LpAb, ResAb)); - - /* Try next possible mode */ - NextMode = SkHWSenseGetNext(pAC, IoC, Port); - SkHWLinkDown(pAC, IoC, Port); - if (Done == SK_AND_DUP_CAP) { - /* GoTo next mode */ - SkHWSenseSetNext(pAC, IoC, Port, NextMode); - } - - return(SK_HW_PS_RESTART); - } - /* - * Dummy Read extended status to prevent extra link down/ups - * (clear Page Received bit if set) - */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_EXP, &ExtStat); - - return(SK_HW_PS_LINK); - } - - /* AutoNeg not done, but HW link is up. Check for timeouts */ - pPrt->PAutoNegTimeOut++; - if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { - /* Increase the Timeout counter */ - pPrt->PAutoNegTOCt++; - - /* Timeout occured */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoNeg timeout Port %d\n", Port)); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { - /* Set Link manually up */ - SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Set manual full duplex Port %d\n", Port)); - } - - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg == SK_LIPA_AUTO && - pPrt->PAutoNegTOCt >= SK_MAX_ANEG_TO) { - /* - * This is rather complicated. - * we need to check here whether the LIPA_AUTO - * we saw before is false alert. We saw at one - * switch ( SR8800) that on boot time it sends - * just one auto-neg packet and does no further - * auto-negotiation. - * Solution: we restart the autosensing after - * a few timeouts. - */ - pPrt->PAutoNegTOCt = 0; - pPrt->PLipaAutoNeg = SK_LIPA_UNKNOWN; - SkHWInitDefSense(pAC, IoC, Port); - } - - /* Do the restart */ - return(SK_HW_PS_RESTART); - } - } - else { - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - /* - * Link sync (GP) and so assume a good connection. But if not received - * a bunch of frames received in a time slot (maybe broken tx cable) - * the port is restart. - */ - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpXmac */ - - -/****************************************************************************** - * - * SkGePortCheckUpBcom() - Check if the link is up on Bcom PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpBcom( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 PhyStat; /* Phy Status Register */ - SK_U16 ResAb; /* Master/Slave resolution */ - SK_U16 Ctrl; /* Broadcom control flags */ -#ifdef DEBUG - SK_U16 LpAb; - SK_U16 ExtStat; -#endif /* DEBUG */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Check for No HCD Link events (#10523) */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &Isrc); - -#ifdef xDEBUG - if ((Isrc & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) == - (PHY_B_IS_SCR_S_ER | PHY_B_IS_RRS_CHANGE | PHY_B_IS_LRS_CHANGE)) { - - SK_U32 Stat1, Stat2, Stat3; - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp1 - Stat: %x, Mask: %x", - (void *)Isrc, - (void *)Stat1); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "Ctrl/Stat: %x, AN Adv/LP: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - } -#endif /* DEBUG */ - - if ((Isrc & (PHY_B_IS_NO_HDCL /* | PHY_B_IS_NO_HDC */)) != 0) { - /* - * Workaround BCom Errata: - * enable and disable loopback mode if "NO HCD" occurs. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Ctrl); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, - (SK_U16)(Ctrl | PHY_CT_LOOP)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, - (SK_U16)(Ctrl & ~PHY_CT_LOOP)); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("No HCD Link event, Port %d\n", Port)); -#ifdef xDEBUG - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "No HCD link event, port %d.", - (void *)Port, - (void *)NULL); -#endif /* DEBUG */ - } - - /* Not obsolete: link status bit is latched to 0 and autoclearing! */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - -#ifdef xDEBUG - { - SK_U32 Stat1, Stat2, Stat3; - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_MASK, &Stat1); - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp1a - Stat: %x, Mask: %x", - (void *)Isrc, - (void *)Stat1); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - Stat1 = Stat1 << 16 | PhyStat; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "Ctrl/Stat: %x, AN Adv/LP: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_EXP, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); - Stat2 = Stat2 << 16 | ResAb; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "AN Exp/IEEE Ext: %x, 1000T Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - - Stat1 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, &Stat1); - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_P_EXT_STAT, &Stat2); - Stat1 = Stat1 << 16 | Stat2; - Stat2 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Stat2); - Stat3 = 0; - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &Stat3); - Stat2 = Stat2 << 16 | Stat3; - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "PHY Ext Ctrl/Stat: %x, Aux Ctrl/Stat: %x", - (void *)Stat1, - (void *)Stat2); - } -#endif /* DEBUG */ - - /* - * Here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_STAT, &PhyStat); - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); - - if ((ResAb & PHY_B_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault port %d\n", Port)); - - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - - return(SK_HW_PS_RESTART); - } - - if ((PhyStat & PHY_ST_LSYNC) == 0) { - return(SK_HW_PS_NONE); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Port %d, ResAb: 0x%04X\n", Port, ResAb)); - - if (AutoNeg) { - if ((PhyStat & PHY_ST_AN_OVER) != 0) { - - SkHWLinkUp(pAC, IoC, Port); - - Done = SkMacAutoNegDone(pAC, IoC, Port); - - if (Done != SK_AND_OK) { -#ifdef DEBUG - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", - Port, LpAb, ExtStat)); -#endif /* DEBUG */ - return(SK_HW_PS_RESTART); - } - else { -#ifdef xDEBUG - /* Dummy read ISR to prevent extra link downs/ups */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); - - if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp2 - Stat: %x", - (void *)ExtStat, - (void *)NULL); - } -#endif /* DEBUG */ - return(SK_HW_PS_LINK); - } - } - } - else { /* !AutoNeg */ - /* Link is up and we don't need more. */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - -#ifdef xDEBUG - /* Dummy read ISR to prevent extra link downs/ups */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_INT_STAT, &ExtStat); - - if ((ExtStat & ~(PHY_B_IS_HCT | PHY_B_IS_LCT)) != 0) { - CMSMPrintString( - pAC->pConfigTable, - MSG_TYPE_RUNTIME_INFO, - "CheckUp3 - Stat: %x", - (void *)ExtStat, - (void *)NULL); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpBcom */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGePortCheckUpGmac() - Check if the link is up on Marvell PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpGmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 PhyIsrc; /* PHY Interrupt source */ - SK_U16 PhyStat; /* PPY Status */ - SK_U16 PhySpecStat;/* PHY Specific Status */ - SK_U16 ResAb; /* Master/Slave resolution */ - SK_EVPARA Para; -#ifdef DEBUG - SK_U16 Word; /* I/O helper */ -#endif /* DEBUG */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - - /* Read PHY Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("CheckUp Port %d, PhyStat: 0x%04X\n", Port, PhyStat)); - - /* Read PHY Interrupt Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_INT_STAT, &PhyIsrc); - - if ((PhyIsrc & PHY_M_IS_AN_COMPL) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Negotiation Completed, PhyIsrc: 0x%04X\n", PhyIsrc)); - } - - if ((PhyIsrc & PHY_M_IS_LSP_CHANGE) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Link Speed Changed, PhyIsrc: 0x%04X\n", PhyIsrc)); - } - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); - - if ((ResAb & PHY_B_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault port %d\n", Port)); - - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - - return(SK_HW_PS_RESTART); - } - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Phy1000BT: 0x%04X, PhySpecStat: 0x%04X\n", ResAb, PhySpecStat)); - -#ifdef DEBUG - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_EXP, &Word); - - if ((PhyIsrc & PHY_M_IS_AN_PR) != 0 || (Word & PHY_ANE_RX_PG) != 0 || - (PhySpecStat & PHY_M_PS_PAGE_REC) != 0) { - /* Read PHY Next Page Link Partner */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_NEPG_LP, &Word); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Page Received, NextPage: 0x%04X\n", Word)); - } -#endif /* DEBUG */ - - if ((PhySpecStat & PHY_M_PS_LINK_UP) == 0) { - return(SK_HW_PS_NONE); - } - - if ((PhySpecStat & PHY_M_PS_DOWNS_STAT) != 0 || - (PhyIsrc & PHY_M_IS_DOWNSH_DET) != 0) { - /* Downshift detected */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E025, SKERR_SIRQ_E025MSG); - - Para.Para64 = Port; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_DOWNSHIFT_DET, Para); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Downshift detected, PhyIsrc: 0x%04X\n", PhyIsrc)); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; - - pPrt->PCableLen = (SK_U8)((PhySpecStat & PHY_M_PS_CABLE_MSK) >> 7); - - if (AutoNeg) { - /* Auto-Negotiation Over ? */ - if ((PhyStat & PHY_ST_AN_OVER) != 0) { - - SkHWLinkUp(pAC, IoC, Port); - - Done = SkMacAutoNegDone(pAC, IoC, Port); - - if (Done != SK_AND_OK) { - return(SK_HW_PS_RESTART); - } - - return(SK_HW_PS_LINK); - } - } - else { /* !AutoNeg */ - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync, Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpGmac */ -#endif /* YUKON */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkGePortCheckUpLone() - Check if the link is up on Level One PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpLone( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - int Done; - SK_U16 Isrc; /* Interrupt source register */ - SK_U16 LpAb; /* Link Partner Ability */ - SK_U16 ExtStat; /* Extended Status Register */ - SK_U16 PhyStat; /* Phy Status Register */ - SK_U16 StatSum; - SK_U8 NextMode; /* Next AutoSensing Mode */ - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PHWLinkUp) { - return(SK_HW_PS_NONE); - } - - StatSum = pPrt->PIsave; - pPrt->PIsave = 0; - - /* - * here we usually can check whether the link is in sync and - * auto-negotiation is done. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_STAT, &PhyStat); - StatSum |= PhyStat; - - SkMacAutoNegLipaPhy(pAC, IoC, Port, PhyStat); - - if ((PhyStat & PHY_ST_LSYNC) == 0) { - /* Save Auto-negotiation Done bit */ - pPrt->PIsave = (SK_U16)(StatSum & PHY_ST_AN_OVER); -#ifdef DEBUG - if ((pPrt->PIsave & PHY_ST_AN_OVER) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done rescheduled Port %d\n", Port)); - } -#endif /* DEBUG */ - return(SK_HW_PS_NONE); - } - - if (AutoNeg) { - if ((StatSum & PHY_ST_AN_OVER) != 0) { - SkHWLinkUp(pAC, IoC, Port); - Done = SkMacAutoNegDone(pAC, IoC, Port); - if (Done != SK_AND_OK) { - /* Get PHY parameters, for debugging only */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LpAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ExtStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg FAIL Port %d (LpAb %x, 1000TStat %x)\n", - Port, LpAb, ExtStat)); - - /* Try next possible mode */ - NextMode = SkHWSenseGetNext(pAC, IoC, Port); - SkHWLinkDown(pAC, IoC, Port); - if (Done == SK_AND_DUP_CAP) { - /* GoTo next mode */ - SkHWSenseSetNext(pAC, IoC, Port, NextMode); - } - - return(SK_HW_PS_RESTART); - - } - else { - /* - * Dummy Read interrupt status to prevent - * extra link down/ups - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); - return(SK_HW_PS_LINK); - } - } - - /* AutoNeg not done, but HW link is up. Check for timeouts */ - pPrt->PAutoNegTimeOut++; - if (pPrt->PAutoNegTimeOut >= SK_AND_MAX_TO) { - /* Timeout occured */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("AutoNeg timeout Port %d\n", Port)); - if (pPrt->PLinkModeConf == SK_LMODE_AUTOSENSE && - pPrt->PLipaAutoNeg != SK_LIPA_AUTO) { - /* Set Link manually up */ - SkHWSenseSetNext(pAC, IoC, Port, SK_LMODE_FULL); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Set manual full duplex Port %d\n", Port)); - } - - /* Do the restart */ - return(SK_HW_PS_RESTART); - } - } - else { - /* Link is up and we don't need more */ -#ifdef DEBUG - if (pPrt->PLipaAutoNeg == SK_LIPA_AUTO) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("ERROR: Lipa auto detected on port %d\n", Port)); - } -#endif /* DEBUG */ - - /* - * Dummy Read interrupt status to prevent - * extra link down/ups - */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_INT_STAT, &ExtStat); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("Link sync(GP), Port %d\n", Port)); - SkHWLinkUp(pAC, IoC, Port); - - return(SK_HW_PS_LINK); - } - - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpLone */ - - -/****************************************************************************** - * - * SkGePortCheckUpNat() - Check if the link is up on National PHY - * - * return: - * 0 o.k. nothing needed - * 1 Restart needed on this port - * 2 Link came up - */ -static int SkGePortCheckUpNat( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO Context */ -int Port, /* Which port should be checked */ -SK_BOOL AutoNeg) /* Is Auto-negotiation used ? */ -{ - /* todo: National */ - return(SK_HW_PS_NONE); -} /* SkGePortCheckUpNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkGeSirqEvent() - Event Service Routine - * - * Description: - * - * Notes: - */ -int SkGeSirqEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -SK_U32 Event, /* Module specific Event */ -SK_EVPARA Para) /* Event specific Parameter */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_U32 Port; - SK_U32 Val32; - int PortStat; - SK_U8 Val8; -#ifdef GENESIS - SK_U64 Octets; -#endif /* GENESIS */ - - Port = Para.Para32[0]; - pPrt = &pAC->GIni.GP[Port]; - - switch (Event) { - case SK_HWEV_WATIM: - if (pPrt->PState == SK_PRT_RESET) { - - PortStat = SK_HW_PS_NONE; - } - else { - /* Check whether port came up */ - PortStat = SkGePortCheckUp(pAC, IoC, (int)Port); - } - - switch (PortStat) { - case SK_HW_PS_RESTART: - if (pPrt->PHWLinkUp) { - /* Set Link to down */ - SkHWLinkDown(pAC, IoC, (int)Port); - - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - /* Restart needed */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - break; - - case SK_HW_PS_LINK: - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_UP, Para); - break; - } - - /* Start again the check Timer */ - if (pPrt->PHWLinkUp) { - Val32 = SK_WA_ACT_TIME; - } - else { - Val32 = SK_WA_INA_TIME; - } - - /* Todo: still needed for non-XMAC PHYs??? */ - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, Val32, - SKGE_HWAC, SK_HWEV_WATIM, Para); - break; - - case SK_HWEV_PORT_START: - if (pPrt->PHWLinkUp) { - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - SkHWLinkDown(pAC, IoC, (int)Port); - - /* Schedule Port RESET */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_PORT_RESET, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - break; - - case SK_HWEV_PORT_STOP: - if (pPrt->PHWLinkUp) { - /* - * Signal directly to RLMT to ensure correct - * sequence of SWITCH and RESET event. - */ - SkRlmtEvent(pAC, IoC, SK_RLMT_LINK_DOWN, Para); - } - - /* Stop Workaround Timer */ - SkTimerStop(pAC, IoC, &pPrt->PWaTimer); - - SkHWLinkDown(pAC, IoC, (int)Port); - break; - - case SK_HWEV_UPDATE_STAT: - /* We do NOT need to update any statistics */ - break; - - case SK_HWEV_CLEAR_STAT: - /* We do NOT need to clear any statistics */ - for (Port = 0; Port < (SK_U32)pAC->GIni.GIMacsFound; Port++) { - pPrt->PPrevRx = 0; - pPrt->PPrevFcs = 0; - pPrt->PPrevShorts = 0; - } - break; - - case SK_HWEV_SET_LMODE: - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PLinkModeConf != Val8) { - /* Set New link mode */ - pPrt->PLinkModeConf = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_FLOWMODE: - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PFlowCtrlMode != Val8) { - /* Set New Flow Control mode */ - pPrt->PFlowCtrlMode = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_ROLE: - /* not possible for fiber */ - if (!pAC->GIni.GICopperType) { - break; - } - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PMSMode != Val8) { - /* Set New Role (Master/Slave) mode */ - pPrt->PMSMode = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - - case SK_HWEV_SET_SPEED: - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - break; - } - Val8 = (SK_U8)Para.Para32[1]; - if (pPrt->PLinkSpeed != Val8) { - /* Set New Speed parameter */ - pPrt->PLinkSpeed = Val8; - - /* Restart Port */ - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para); - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); - } - break; - -#ifdef GENESIS - case SK_HWEV_HALFDUP_CHK: - if (pAC->GIni.GIGenesis) { - /* - * half duplex hangup workaround. - * See packet arbiter timeout interrupt for description - */ - pPrt->HalfDupTimerActive = SK_FALSE; - if (pPrt->PLinkModeStatus == SK_LMODE_STAT_HALF || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOHALF) { - /* Snap statistic counters */ - (void)SkXmUpdateStats(pAC, IoC, Port); - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_HI, &Val32); - - Octets = (SK_U64)Val32 << 32; - - (void)SkXmMacStatistic(pAC, IoC, Port, XM_TXO_OK_LO, &Val32); - - Octets += Val32; - - if (pPrt->LastOctets == Octets) { - /* Tx hanging, a FIFO flush restarts it */ - SkMacFlushTxFifo(pAC, IoC, Port); - } - } - } - break; -#endif /* GENESIS */ - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_SIRQ_E001, SKERR_SIRQ_E001MSG); - break; - } - - return(0); -} /* SkGeSirqEvent */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkPhyIsrBcom() - PHY interrupt service routine - * - * Description: handles all interrupts from BCom PHY - * - * Returns: N/A - */ -static void SkPhyIsrBcom( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_EVPARA Para; - - pPrt = &pAC->GIni.GP[Port]; - - if ((IStatus & PHY_B_IS_PSE) != 0) { - /* Incorrectable pair swap error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW | SK_ERRCL_INIT, SKERR_SIRQ_E022, - SKERR_SIRQ_E022MSG); - } - - if ((IStatus & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) != 0) { - - SkHWLinkDown(pAC, IoC, Port); - - Para.Para32[0] = (SK_U32)Port; - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - } - -} /* SkPhyIsrBcom */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkPhyIsrGmac() - PHY interrupt service routine - * - * Description: handles all interrupts from Marvell PHY - * - * Returns: N/A - */ -static void SkPhyIsrGmac( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - SK_EVPARA Para; - SK_U16 Word; - - pPrt = &pAC->GIni.GP[Port]; - - if ((IStatus & (PHY_M_IS_AN_PR | PHY_M_IS_LST_CHANGE)) != 0) { - - SkHWLinkDown(pAC, IoC, Port); - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &Word); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg.Adv: 0x%04X\n", Word)); - - /* Set Auto-negotiation advertisement */ - if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) { - /* restore Asymmetric Pause bit */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, - (SK_U16)(Word | PHY_M_AN_ASP)); - } - - Para.Para32[0] = (SK_U32)Port; - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - - if ((IStatus & PHY_M_IS_AN_ERROR) != 0) { - /* Auto-Negotiation Error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E023, SKERR_SIRQ_E023MSG); - } - - if ((IStatus & PHY_M_IS_FIFO_ERROR) != 0) { - /* FIFO Overflow/Underrun Error */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E024, SKERR_SIRQ_E024MSG); - } - -} /* SkPhyIsrGmac */ -#endif /* YUKON */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkPhyIsrLone() - PHY interrupt service routine - * - * Description: handles all interrupts from LONE PHY - * - * Returns: N/A - */ -static void SkPhyIsrLone( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* Io Context */ -int Port, /* Port Num = PHY Num */ -SK_U16 IStatus) /* Interrupt Status */ -{ - SK_EVPARA Para; - - if (IStatus & (PHY_L_IS_DUP | PHY_L_IS_ISOL)) { - - SkHWLinkDown(pAC, IoC, Port); - - Para.Para32[0] = (SK_U32)Port; - /* Signal to RLMT */ - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - } - -} /* SkPhyIsrLone */ -#endif /* OTHER_PHY */ - -/* End of File */ diff --git a/drivers/net/sk98lin/ski2c.c b/drivers/net/sk98lin/ski2c.c deleted file mode 100644 index 79bf57cb5326..000000000000 --- a/drivers/net/sk98lin/ski2c.c +++ /dev/null @@ -1,1296 +0,0 @@ -/****************************************************************************** - * - * Name: ski2c.c - * Project: Gigabit Ethernet Adapters, TWSI-Module - * Version: $Revision: 1.59 $ - * Date: $Date: 2003/10/20 09:07:25 $ - * Purpose: Functions to access Voltage and Temperature Sensor - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - * I2C Protocol - */ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: ski2c.c,v 1.59 2003/10/20 09:07:25 rschmidt Exp $ (C) Marvell. "; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/lm80.h" -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - I2C protocol implementation. - - General Description: - - The I2C protocol is used for the temperature sensors and for - the serial EEPROM which hold the configuration. - - This file covers functions that allow to read write and do - some bulk requests a specified I2C address. - - The Genesis has 2 I2C buses. One for the EEPROM which holds - the VPD Data and one for temperature and voltage sensor. - The following picture shows the I2C buses, I2C devices and - their control registers. - - Note: The VPD functions are in skvpd.c -. -. PCI Config I2C Bus for VPD Data: -. -. +------------+ -. | VPD EEPROM | -. +------------+ -. | -. | <-- I2C -. | -. +-----------+-----------+ -. | | -. +-----------------+ +-----------------+ -. | PCI_VPD_ADR_REG | | PCI_VPD_DAT_REG | -. +-----------------+ +-----------------+ -. -. -. I2C Bus for LM80 sensor: -. -. +-----------------+ -. | Temperature and | -. | Voltage Sensor | -. | LM80 | -. +-----------------+ -. | -. | -. I2C --> | -. | -. +----+ -. +-------------->| OR |<--+ -. | +----+ | -. +------+------+ | -. | | | -. +--------+ +--------+ +----------+ -. | B2_I2C | | B2_I2C | | B2_I2C | -. | _CTRL | | _DATA | | _SW | -. +--------+ +--------+ +----------+ -. - The I2C bus may be driven by the B2_I2C_SW or by the B2_I2C_CTRL - and B2_I2C_DATA registers. - For driver software it is recommended to use the I2C control and - data register, because I2C bus timing is done by the ASIC and - an interrupt may be received when the I2C request is completed. - - Clock Rate Timing: MIN MAX generated by - VPD EEPROM: 50 kHz 100 kHz HW - LM80 over I2C Ctrl/Data reg. 50 kHz 100 kHz HW - LM80 over B2_I2C_SW register 0 400 kHz SW - - Note: The clock generated by the hardware is dependend on the - PCI clock. If the PCI bus clock is 33 MHz, the I2C/VPD - clock is 50 kHz. - */ -intro() -{} -#endif - -#ifdef SK_DIAG -/* - * I2C Fast Mode timing values used by the LM80. - * If new devices are added to the I2C bus the timing values have to be checked. - */ -#ifndef I2C_SLOW_TIMING -#define T_CLK_LOW 1300L /* clock low time in ns */ -#define T_CLK_HIGH 600L /* clock high time in ns */ -#define T_DATA_IN_SETUP 100L /* data in Set-up Time */ -#define T_START_HOLD 600L /* start condition hold time */ -#define T_START_SETUP 600L /* start condition Set-up time */ -#define T_STOP_SETUP 600L /* stop condition Set-up time */ -#define T_BUS_IDLE 1300L /* time the bus must free after Tx */ -#define T_CLK_2_DATA_OUT 900L /* max. clock low to data output valid */ -#else /* I2C_SLOW_TIMING */ -/* I2C Standard Mode Timing */ -#define T_CLK_LOW 4700L /* clock low time in ns */ -#define T_CLK_HIGH 4000L /* clock high time in ns */ -#define T_DATA_IN_SETUP 250L /* data in Set-up Time */ -#define T_START_HOLD 4000L /* start condition hold time */ -#define T_START_SETUP 4700L /* start condition Set-up time */ -#define T_STOP_SETUP 4000L /* stop condition Set-up time */ -#define T_BUS_IDLE 4700L /* time the bus must free after Tx */ -#endif /* !I2C_SLOW_TIMING */ - -#define NS2BCLK(x) (((x)*125)/10000) - -/* - * I2C Wire Operations - * - * About I2C_CLK_LOW(): - * - * The Data Direction bit (I2C_DATA_DIR) has to be set to input when setting - * clock to low, to prevent the ASIC and the I2C data client from driving the - * serial data line simultaneously (ASIC: last bit of a byte = '1', I2C client - * send an 'ACK'). See also Concentrator Bugreport No. 10192. - */ -#define I2C_DATA_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA) -#define I2C_DATA_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA) -#define I2C_DATA_OUT(IoC) SK_I2C_SET_BIT(IoC, I2C_DATA_DIR) -#define I2C_DATA_IN(IoC) SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA) -#define I2C_CLK_HIGH(IoC) SK_I2C_SET_BIT(IoC, I2C_CLK) -#define I2C_CLK_LOW(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK | I2C_DATA_DIR) -#define I2C_START_COND(IoC) SK_I2C_CLR_BIT(IoC, I2C_CLK) - -#define NS2CLKT(x) ((x*125L)/10000) - -/*--------------- I2C Interface Register Functions --------------- */ - -/* - * sending one bit - */ -void SkI2cSndBit( -SK_IOC IoC, /* I/O Context */ -SK_U8 Bit) /* Bit to send */ -{ - I2C_DATA_OUT(IoC); - if (Bit) { - I2C_DATA_HIGH(IoC); - } - else { - I2C_DATA_LOW(IoC); - } - SkDgWaitTime(IoC, NS2BCLK(T_DATA_IN_SETUP)); - I2C_CLK_HIGH(IoC); - SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); - I2C_CLK_LOW(IoC); -} /* SkI2cSndBit*/ - - -/* - * Signal a start to the I2C Bus. - * - * A start is signaled when data goes to low in a high clock cycle. - * - * Ends with Clock Low. - * - * Status: not tested - */ -void SkI2cStart( -SK_IOC IoC) /* I/O Context */ -{ - /* Init data and Clock to output lines */ - /* Set Data high */ - I2C_DATA_OUT(IoC); - I2C_DATA_HIGH(IoC); - /* Set Clock high */ - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_START_SETUP)); - - /* Set Data Low */ - I2C_DATA_LOW(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_START_HOLD)); - - /* Clock low without Data to Input */ - I2C_START_COND(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW)); -} /* SkI2cStart */ - - -void SkI2cStop( -SK_IOC IoC) /* I/O Context */ -{ - /* Init data and Clock to output lines */ - /* Set Data low */ - I2C_DATA_OUT(IoC); - I2C_DATA_LOW(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); - - /* Set Clock high */ - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_STOP_SETUP)); - - /* - * Set Data High: Do it by setting the Data Line to Input. - * Because of a pull up resistor the Data Line - * floods to high. - */ - I2C_DATA_IN(IoC); - - /* - * When I2C activity is stopped - * o DATA should be set to input and - * o CLOCK should be set to high! - */ - SkDgWaitTime(IoC, NS2BCLK(T_BUS_IDLE)); -} /* SkI2cStop */ - - -/* - * Receive just one bit via the I2C bus. - * - * Note: Clock must be set to LOW before calling this function. - * - * Returns The received bit. - */ -int SkI2cRcvBit( -SK_IOC IoC) /* I/O Context */ -{ - int Bit; - SK_U8 I2cSwCtrl; - - /* Init data as input line */ - I2C_DATA_IN(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_2_DATA_OUT)); - - I2C_CLK_HIGH(IoC); - - SkDgWaitTime(IoC, NS2BCLK(T_CLK_HIGH)); - - SK_I2C_GET_SW(IoC, &I2cSwCtrl); - - Bit = (I2cSwCtrl & I2C_DATA) ? 1 : 0; - - I2C_CLK_LOW(IoC); - SkDgWaitTime(IoC, NS2BCLK(T_CLK_LOW-T_CLK_2_DATA_OUT)); - - return(Bit); -} /* SkI2cRcvBit */ - - -/* - * Receive an ACK. - * - * returns 0 If acknowledged - * 1 in case of an error - */ -int SkI2cRcvAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - */ - return(SkI2cRcvBit(IoC) != 0); -} /* SkI2cRcvAck */ - - -/* - * Send an NACK. - */ -void SkI2cSndNAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - */ - SkI2cSndBit(IoC, 1); -} /* SkI2cSndNAck */ - - -/* - * Send an ACK. - */ -void SkI2cSndAck( -SK_IOC IoC) /* I/O Context */ -{ - /* - * Received bit must be zero. - */ - SkI2cSndBit(IoC, 0); -} /* SkI2cSndAck */ - - -/* - * Send one byte to the I2C device and wait for ACK. - * - * Return acknowleged status. - */ -int SkI2cSndByte( -SK_IOC IoC, /* I/O Context */ -int Byte) /* byte to send */ -{ - int i; - - for (i = 0; i < 8; i++) { - if (Byte & (1<<(7-i))) { - SkI2cSndBit(IoC, 1); - } - else { - SkI2cSndBit(IoC, 0); - } - } - - return(SkI2cRcvAck(IoC)); -} /* SkI2cSndByte */ - - -/* - * Receive one byte and ack it. - * - * Return byte. - */ -int SkI2cRcvByte( -SK_IOC IoC, /* I/O Context */ -int Last) /* Last Byte Flag */ -{ - int i; - int Byte = 0; - - for (i = 0; i < 8; i++) { - Byte <<= 1; - Byte |= SkI2cRcvBit(IoC); - } - - if (Last) { - SkI2cSndNAck(IoC); - } - else { - SkI2cSndAck(IoC); - } - - return(Byte); -} /* SkI2cRcvByte */ - - -/* - * Start dialog and send device address - * - * Return 0 if acknowleged, 1 in case of an error - */ -int SkI2cSndDev( -SK_IOC IoC, /* I/O Context */ -int Addr, /* Device Address */ -int Rw) /* Read / Write Flag */ -{ - SkI2cStart(IoC); - Rw = ~Rw; - Rw &= I2C_WRITE; - return(SkI2cSndByte(IoC, (Addr<<1) | Rw)); -} /* SkI2cSndDev */ - -#endif /* SK_DIAG */ - -/*----------------- I2C CTRL Register Functions ----------*/ - -/* - * waits for a completion of an I2C transfer - * - * returns 0: success, transfer completes - * 1: error, transfer does not complete, I2C transfer - * killed, wait loop terminated. - */ -static int SkI2cWait( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Event) /* complete event to wait for (I2C_READ or I2C_WRITE) */ -{ - SK_U64 StartTime; - SK_U64 CurrentTime; - SK_U32 I2cCtrl; - - StartTime = SkOsGetTime(pAC); - - do { - CurrentTime = SkOsGetTime(pAC); - - if (CurrentTime - StartTime > SK_TICKS_PER_SEC / 8) { - - SK_I2C_STOP(IoC); -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E002, SKERR_I2C_E002MSG); -#endif /* !SK_DIAG */ - return(1); - } - - SK_I2C_GET_CTL(IoC, &I2cCtrl); - -#ifdef xYUKON_DBG - printf("StartTime=%lu, CurrentTime=%lu\n", - StartTime, CurrentTime); - if (kbhit()) { - return(1); - } -#endif /* YUKON_DBG */ - - } while ((I2cCtrl & I2C_FLAG) == (SK_U32)Event << 31); - - return(0); -} /* SkI2cWait */ - - -/* - * waits for a completion of an I2C transfer - * - * Returns - * Nothing - */ -void SkI2cWaitIrq( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - SK_SENSOR *pSen; - SK_U64 StartTime; - SK_U32 IrqSrc; - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - - if (pSen->SenState == SK_SEN_IDLE) { - return; - } - - StartTime = SkOsGetTime(pAC); - - do { - if (SkOsGetTime(pAC) - StartTime > SK_TICKS_PER_SEC / 8) { - - SK_I2C_STOP(IoC); -#ifndef SK_DIAG - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E016, SKERR_I2C_E016MSG); -#endif /* !SK_DIAG */ - return; - } - - SK_IN32(IoC, B0_ISRC, &IrqSrc); - - } while ((IrqSrc & IS_I2C_READY) == 0); - - pSen->SenState = SK_SEN_IDLE; - return; -} /* SkI2cWaitIrq */ - -/* - * writes a single byte or 4 bytes into the I2C device - * - * returns 0: success - * 1: error - */ -static int SkI2cWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 I2cData, /* I2C Data to write */ -int I2cDev, /* I2C Device Address */ -int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ -int I2cReg, /* I2C Device Register Address */ -int I2cBurst) /* I2C Burst Flag */ -{ - SK_OUT32(IoC, B2_I2C_DATA, I2cData); - - SK_I2C_CTL(IoC, I2C_WRITE, I2cDev, I2cDevSize, I2cReg, I2cBurst); - - return(SkI2cWait(pAC, IoC, I2C_WRITE)); -} /* SkI2cWrite*/ - - -#ifdef SK_DIAG -/* - * reads a single byte or 4 bytes from the I2C device - * - * returns the word read - */ -SK_U32 SkI2cRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int I2cDev, /* I2C Device Address */ -int I2cDevSize, /* I2C Device Size (e.g. I2C_025K_DEV or I2C_2K_DEV) */ -int I2cReg, /* I2C Device Register Address */ -int I2cBurst) /* I2C Burst Flag */ -{ - SK_U32 Data; - - SK_OUT32(IoC, B2_I2C_DATA, 0); - SK_I2C_CTL(IoC, I2C_READ, I2cDev, I2cDevSize, I2cReg, I2cBurst); - - if (SkI2cWait(pAC, IoC, I2C_READ) != 0) { - w_print("%s\n", SKERR_I2C_E002MSG); - } - - SK_IN32(IoC, B2_I2C_DATA, &Data); - - return(Data); -} /* SkI2cRead */ -#endif /* SK_DIAG */ - - -/* - * read a sensor's value - * - * This function reads a sensor's value from the I2C sensor chip. The sensor - * is defined by its index into the sensors database in the struct pAC points - * to. - * Returns - * 1 if the read is completed - * 0 if the read must be continued (I2C Bus still allocated) - */ -static int SkI2cReadSensor( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_SENSOR *pSen) /* Sensor to be read */ -{ - if (pSen->SenRead != NULL) { - return((*pSen->SenRead)(pAC, IoC, pSen)); - } - else { - return(0); /* no success */ - } -} /* SkI2cReadSensor */ - -/* - * Do the Init state 0 initialization - */ -static int SkI2cInit0( -SK_AC *pAC) /* Adapter Context */ -{ - int i; - - /* Begin with first sensor */ - pAC->I2c.CurrSens = 0; - - /* Begin with timeout control for state machine */ - pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; - - /* Set sensor number to zero */ - pAC->I2c.MaxSens = 0; - -#ifndef SK_DIAG - /* Initialize Number of Dummy Reads */ - pAC->I2c.DummyReads = SK_MAX_SENSORS; -#endif - - for (i = 0; i < SK_MAX_SENSORS; i++) { - pAC->I2c.SenTable[i].SenDesc = "unknown"; - pAC->I2c.SenTable[i].SenType = SK_SEN_UNKNOWN; - pAC->I2c.SenTable[i].SenThreErrHigh = 0; - pAC->I2c.SenTable[i].SenThreErrLow = 0; - pAC->I2c.SenTable[i].SenThreWarnHigh = 0; - pAC->I2c.SenTable[i].SenThreWarnLow = 0; - pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; - pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_NONE; - pAC->I2c.SenTable[i].SenValue = 0; - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_NOT_PRESENT; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; - pAC->I2c.SenTable[i].SenRead = NULL; - pAC->I2c.SenTable[i].SenDev = 0; - } - - /* Now we are "INIT data"ed */ - pAC->I2c.InitLevel = SK_INIT_DATA; - return(0); -} /* SkI2cInit0*/ - - -/* - * Do the init state 1 initialization - * - * initialize the following register of the LM80: - * Configuration register: - * - START, noINT, activeLOW, noINT#Clear, noRESET, noCI, noGPO#, noINIT - * - * Interrupt Mask Register 1: - * - all interrupts are Disabled (0xff) - * - * Interrupt Mask Register 2: - * - all interrupts are Disabled (0xff) Interrupt modi doesn't matter. - * - * Fan Divisor/RST_OUT register: - * - Divisors set to 1 (bits 00), all others 0s. - * - * OS# Configuration/Temperature resolution Register: - * - all 0s - * - */ -static int SkI2cInit1( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - int i; - SK_U8 I2cSwCtrl; - SK_GEPORT *pPrt; /* GIni Port struct pointer */ - - if (pAC->I2c.InitLevel != SK_INIT_DATA) { - /* ReInit not needed in I2C module */ - return(0); - } - - /* Set the Direction of I2C-Data Pin to IN */ - SK_I2C_CLR_BIT(IoC, I2C_DATA_DIR | I2C_DATA); - /* Check for 32-Bit Yukon with Low at I2C-Data Pin */ - SK_I2C_GET_SW(IoC, &I2cSwCtrl); - - if ((I2cSwCtrl & I2C_DATA) == 0) { - /* this is a 32-Bit board */ - pAC->GIni.GIYukon32Bit = SK_TRUE; - return(0); - } - - /* Check for 64 Bit Yukon without sensors */ - if (SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_CFG, 0) != 0) { - return(0); - } - - (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_1, 0); - - (void)SkI2cWrite(pAC, IoC, 0xffUL, LM80_ADDR, I2C_025K_DEV, LM80_IMSK_2, 0); - - (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_FAN_CTRL, 0); - - (void)SkI2cWrite(pAC, IoC, 0, LM80_ADDR, I2C_025K_DEV, LM80_TEMP_CTRL, 0); - - (void)SkI2cWrite(pAC, IoC, (SK_U32)LM80_CFG_START, LM80_ADDR, I2C_025K_DEV, - LM80_CFG, 0); - - /* - * MaxSens has to be updated here, because PhyType is not - * set when performing Init Level 0 - */ - pAC->I2c.MaxSens = 5; - - pPrt = &pAC->GIni.GP[0]; - - if (pAC->GIni.GIGenesis) { - if (pPrt->PhyType == SK_PHY_BCOM) { - if (pAC->GIni.GIMacsFound == 1) { - pAC->I2c.MaxSens += 1; - } - else { - pAC->I2c.MaxSens += 3; - } - } - } - else { - pAC->I2c.MaxSens += 3; - } - - for (i = 0; i < pAC->I2c.MaxSens; i++) { - switch (i) { - case 0: - pAC->I2c.SenTable[i].SenDesc = "Temperature"; - pAC->I2c.SenTable[i].SenType = SK_SEN_TEMP; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_TEMP_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_TEMP_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_TEMP_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_TEMP_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_TEMP_IN; - break; - case 1: - pAC->I2c.SenTable[i].SenDesc = "Voltage PCI"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_5V_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_5V_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_5V_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_5V_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT0_IN; - break; - case 2: - pAC->I2c.SenTable[i].SenDesc = "Voltage PCI-IO"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PCI_IO_5V_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PCI_IO_5V_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PCI_IO_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PCI_IO_3V3_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT1_IN; - pAC->I2c.SenTable[i].SenInit = SK_SEN_DYN_INIT_PCI_IO; - break; - case 3: - pAC->I2c.SenTable[i].SenDesc = "Voltage ASIC"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VDD_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VDD_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VDD_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VDD_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT2_IN; - break; - case 4: - if (pAC->GIni.GIGenesis) { - if (pPrt->PhyType == SK_PHY_BCOM) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY A PLL"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PMA"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - } - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage VAUX"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_VAUX_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_VAUX_3V3_HIGH_WARN; - if (pAC->GIni.GIVauxAvail) { - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_VAUX_0V_WARN_ERR; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_VAUX_0V_WARN_ERR; - } - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenReg = LM80_VT3_IN; - break; - case 5: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage Core 1V5"; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_CORE_1V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_CORE_1V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_CORE_1V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_CORE_1V5_LOW_ERR; - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenReg = LM80_VT4_IN; - break; - case 6: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY B PLL"; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 3V3"; - } - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PLL_3V3_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PLL_3V3_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PLL_3V3_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PLL_3V3_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT5_IN; - break; - case 7: - if (pAC->GIni.GIGenesis) { - pAC->I2c.SenTable[i].SenDesc = "Speed Fan"; - pAC->I2c.SenTable[i].SenType = SK_SEN_FAN; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_FAN_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_FAN_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_FAN_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_FAN_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_FAN2_IN; - } - else { - pAC->I2c.SenTable[i].SenDesc = "Voltage PHY 2V5"; - pAC->I2c.SenTable[i].SenType = SK_SEN_VOLT; - pAC->I2c.SenTable[i].SenThreErrHigh = SK_SEN_PHY_2V5_HIGH_ERR; - pAC->I2c.SenTable[i].SenThreWarnHigh = SK_SEN_PHY_2V5_HIGH_WARN; - pAC->I2c.SenTable[i].SenThreWarnLow = SK_SEN_PHY_2V5_LOW_WARN; - pAC->I2c.SenTable[i].SenThreErrLow = SK_SEN_PHY_2V5_LOW_ERR; - pAC->I2c.SenTable[i].SenReg = LM80_VT6_IN; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_INIT | SK_ERRCL_SW, - SKERR_I2C_E001, SKERR_I2C_E001MSG); - break; - } - - pAC->I2c.SenTable[i].SenValue = 0; - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenState = SK_SEN_IDLE; - pAC->I2c.SenTable[i].SenRead = SkLm80ReadSensor; - pAC->I2c.SenTable[i].SenDev = LM80_ADDR; - } - -#ifndef SK_DIAG - pAC->I2c.DummyReads = pAC->I2c.MaxSens; -#endif /* !SK_DIAG */ - - /* Clear I2C IRQ */ - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); - - /* Now we are I/O initialized */ - pAC->I2c.InitLevel = SK_INIT_IO; - return(0); -} /* SkI2cInit1 */ - - -/* - * Init level 2: Start first sensor read. - */ -static int SkI2cInit2( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - int ReadComplete; - SK_SENSOR *pSen; - - if (pAC->I2c.InitLevel != SK_INIT_IO) { - /* ReInit not needed in I2C module */ - /* Init0 and Init2 not permitted */ - return(0); - } - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - SK_ERR_LOG(pAC, SK_ERRCL_INIT, SKERR_I2C_E008, SKERR_I2C_E008MSG); - } - - /* Now we are correctly initialized */ - pAC->I2c.InitLevel = SK_INIT_RUN; - - return(0); -} /* SkI2cInit2*/ - - -/* - * Initialize I2C devices - * - * Get the first voltage value and discard it. - * Go into temperature read mode. A default pointer is not set. - * - * The things to be done depend on the init level in the parameter list: - * Level 0: - * Initialize only the data structures. Do NOT access hardware. - * Level 1: - * Initialize hardware through SK_IN / SK_OUT commands. Do NOT use interrupts. - * Level 2: - * Everything is possible. Interrupts may be used from now on. - * - * return: - * 0 = success - * other = error. - */ -int SkI2cInit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context needed in levels 1 and 2 */ -int Level) /* Init Level */ -{ - - switch (Level) { - case SK_INIT_DATA: - return(SkI2cInit0(pAC)); - case SK_INIT_IO: - return(SkI2cInit1(pAC, IoC)); - case SK_INIT_RUN: - return(SkI2cInit2(pAC, IoC)); - default: - break; - } - - return(0); -} /* SkI2cInit */ - - -#ifndef SK_DIAG - -/* - * Interrupt service function for the I2C Interface - * - * Clears the Interrupt source - * - * Reads the register and check it for sending a trap. - * - * Starts the timer if necessary. - */ -void SkI2cIsr( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC) /* I/O Context */ -{ - SK_EVPARA Para; - - /* Clear I2C IRQ */ - SK_OUT32(IoC, B2_I2C_IRQ, I2C_CLR_IRQ); - - Para.Para64 = 0; - SkEventQueue(pAC, SKGE_I2C, SK_I2CEV_IRQ, Para); -} /* SkI2cIsr */ - - -/* - * Check this sensors Value against the threshold and send events. - */ -static void SkI2cCheckSensor( -SK_AC *pAC, /* Adapter Context */ -SK_SENSOR *pSen) -{ - SK_EVPARA ParaLocal; - SK_BOOL TooHigh; /* Is sensor too high? */ - SK_BOOL TooLow; /* Is sensor too low? */ - SK_U64 CurrTime; /* Current Time */ - SK_BOOL DoTrapSend; /* We need to send a trap */ - SK_BOOL DoErrLog; /* We need to log the error */ - SK_BOOL IsError; /* We need to log the error */ - - /* Check Dummy Reads first */ - if (pAC->I2c.DummyReads > 0) { - pAC->I2c.DummyReads--; - return; - } - - /* Get the current time */ - CurrTime = SkOsGetTime(pAC); - - /* Set para to the most useful setting: The current sensor. */ - ParaLocal.Para64 = (SK_U64)pAC->I2c.CurrSens; - - /* Check the Value against the thresholds. First: Error Thresholds */ - TooHigh = (pSen->SenValue > pSen->SenThreErrHigh); - TooLow = (pSen->SenValue < pSen->SenThreErrLow); - - IsError = SK_FALSE; - if (TooHigh || TooLow) { - /* Error condition is satisfied */ - DoTrapSend = SK_TRUE; - DoErrLog = SK_TRUE; - - /* Now error condition is satisfied */ - IsError = SK_TRUE; - - if (pSen->SenErrFlag == SK_SEN_ERR_ERR) { - /* This state is the former one */ - - /* So check first whether we have to send a trap */ - if (pSen->SenLastErrTrapTS + SK_SEN_ERR_TR_HOLD > - CurrTime) { - /* - * Do NOT send the Trap. The hold back time - * has to run out first. - */ - DoTrapSend = SK_FALSE; - } - - /* Check now whether we have to log an Error */ - if (pSen->SenLastErrLogTS + SK_SEN_ERR_LOG_HOLD > - CurrTime) { - /* - * Do NOT log the error. The hold back time - * has to run out first. - */ - DoErrLog = SK_FALSE; - } - } - else { - /* We came from a different state -> Set Begin Time Stamp */ - pSen->SenBegErrTS = CurrTime; - pSen->SenErrFlag = SK_SEN_ERR_ERR; - } - - if (DoTrapSend) { - /* Set current Time */ - pSen->SenLastErrTrapTS = CurrTime; - pSen->SenErrCts++; - - /* Queue PNMI Event */ - SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? - SK_PNMI_EVT_SEN_ERR_UPP : - SK_PNMI_EVT_SEN_ERR_LOW), - ParaLocal); - } - - if (DoErrLog) { - /* Set current Time */ - pSen->SenLastErrLogTS = CurrTime; - - if (pSen->SenType == SK_SEN_TEMP) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E011, SKERR_I2C_E011MSG); - } - else if (pSen->SenType == SK_SEN_VOLT) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E012, SKERR_I2C_E012MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E015, SKERR_I2C_E015MSG); - } - } - } - - /* Check the Value against the thresholds */ - /* 2nd: Warning thresholds */ - TooHigh = (pSen->SenValue > pSen->SenThreWarnHigh); - TooLow = (pSen->SenValue < pSen->SenThreWarnLow); - - if (!IsError && (TooHigh || TooLow)) { - /* Error condition is satisfied */ - DoTrapSend = SK_TRUE; - DoErrLog = SK_TRUE; - - if (pSen->SenErrFlag == SK_SEN_ERR_WARN) { - /* This state is the former one */ - - /* So check first whether we have to send a trap */ - if (pSen->SenLastWarnTrapTS + SK_SEN_WARN_TR_HOLD > CurrTime) { - /* - * Do NOT send the Trap. The hold back time - * has to run out first. - */ - DoTrapSend = SK_FALSE; - } - - /* Check now whether we have to log an Error */ - if (pSen->SenLastWarnLogTS + SK_SEN_WARN_LOG_HOLD > CurrTime) { - /* - * Do NOT log the error. The hold back time - * has to run out first. - */ - DoErrLog = SK_FALSE; - } - } - else { - /* We came from a different state -> Set Begin Time Stamp */ - pSen->SenBegWarnTS = CurrTime; - pSen->SenErrFlag = SK_SEN_ERR_WARN; - } - - if (DoTrapSend) { - /* Set current Time */ - pSen->SenLastWarnTrapTS = CurrTime; - pSen->SenWarnCts++; - - /* Queue PNMI Event */ - SkEventQueue(pAC, SKGE_PNMI, (TooHigh ? - SK_PNMI_EVT_SEN_WAR_UPP : - SK_PNMI_EVT_SEN_WAR_LOW), - ParaLocal); - } - - if (DoErrLog) { - /* Set current Time */ - pSen->SenLastWarnLogTS = CurrTime; - - if (pSen->SenType == SK_SEN_TEMP) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E009, SKERR_I2C_E009MSG); - } - else if (pSen->SenType == SK_SEN_VOLT) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E010, SKERR_I2C_E010MSG); - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E014, SKERR_I2C_E014MSG); - } - } - } - - /* Check for NO error at all */ - if (!IsError && !TooHigh && !TooLow) { - /* Set o.k. Status if no error and no warning condition */ - pSen->SenErrFlag = SK_SEN_ERR_OK; - } - - /* End of check against the thresholds */ - - /* Bug fix AF: 16.Aug.2001: Correct the init base - * of LM80 sensor. - */ - if (pSen->SenInit == SK_SEN_DYN_INIT_PCI_IO) { - - pSen->SenInit = SK_SEN_DYN_INIT_NONE; - - if (pSen->SenValue > SK_SEN_PCI_IO_RANGE_LIMITER) { - /* 5V PCI-IO Voltage */ - pSen->SenThreWarnLow = SK_SEN_PCI_IO_5V_LOW_WARN; - pSen->SenThreErrLow = SK_SEN_PCI_IO_5V_LOW_ERR; - } - else { - /* 3.3V PCI-IO Voltage */ - pSen->SenThreWarnHigh = SK_SEN_PCI_IO_3V3_HIGH_WARN; - pSen->SenThreErrHigh = SK_SEN_PCI_IO_3V3_HIGH_ERR; - } - } - -#ifdef TEST_ONLY - /* Dynamic thresholds also for VAUX of LM80 sensor */ - if (pSen->SenInit == SK_SEN_DYN_INIT_VAUX) { - - pSen->SenInit = SK_SEN_DYN_INIT_NONE; - - /* 3.3V VAUX Voltage */ - if (pSen->SenValue > SK_SEN_VAUX_RANGE_LIMITER) { - pSen->SenThreWarnLow = SK_SEN_VAUX_3V3_LOW_WARN; - pSen->SenThreErrLow = SK_SEN_VAUX_3V3_LOW_ERR; - } - /* 0V VAUX Voltage */ - else { - pSen->SenThreWarnHigh = SK_SEN_VAUX_0V_WARN_ERR; - pSen->SenThreErrHigh = SK_SEN_VAUX_0V_WARN_ERR; - } - } - - /* - * Check initialization state: - * The VIO Thresholds need adaption - */ - if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && - pSen->SenValue > SK_SEN_WARNLOW2C && - pSen->SenValue < SK_SEN_WARNHIGH2) { - pSen->SenThreErrLow = SK_SEN_ERRLOW2C; - pSen->SenThreWarnLow = SK_SEN_WARNLOW2C; - pSen->SenInit = SK_TRUE; - } - - if (!pSen->SenInit && pSen->SenReg == LM80_VT1_IN && - pSen->SenValue > SK_SEN_WARNLOW2 && - pSen->SenValue < SK_SEN_WARNHIGH2C) { - pSen->SenThreErrHigh = SK_SEN_ERRHIGH2C; - pSen->SenThreWarnHigh = SK_SEN_WARNHIGH2C; - pSen->SenInit = SK_TRUE; - } -#endif - - if (pSen->SenInit != SK_SEN_DYN_INIT_NONE) { - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_I2C_E013, SKERR_I2C_E013MSG); - } -} /* SkI2cCheckSensor */ - - -/* - * The only Event to be served is the timeout event - * - */ -int SkI2cEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Module specific Event */ -SK_EVPARA Para) /* Event specific Parameter */ -{ - int ReadComplete; - SK_SENSOR *pSen; - SK_U32 Time; - SK_EVPARA ParaLocal; - int i; - - /* New case: no sensors */ - if (pAC->I2c.MaxSens == 0) { - return(0); - } - - switch (Event) { - case SK_I2CEV_IRQ: - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - /* Check sensor against defined thresholds */ - SkI2cCheckSensor(pAC, pSen); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens >= pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - else { - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_WATCH_SM; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, SK_I2C_TIM_WATCH, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - break; - case SK_I2CEV_TIM: - if (pAC->I2c.TimerMode == SK_TIMER_NEW_GAUGING) { - - ParaLocal.Para64 = (SK_U64)0; - SkTimerStop(pAC, IoC, &pAC->I2c.SenTimer); - - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - ReadComplete = SkI2cReadSensor(pAC, IoC, pSen); - - if (ReadComplete) { - /* Check sensor against defined thresholds */ - SkI2cCheckSensor(pAC, pSen); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - } - else { - pSen = &pAC->I2c.SenTable[pAC->I2c.CurrSens]; - pSen->SenErrFlag = SK_SEN_ERR_FAULTY; - SK_I2C_STOP(IoC); - - /* Increment Current sensor and set appropriate Timeout */ - pAC->I2c.CurrSens++; - if (pAC->I2c.CurrSens == pAC->I2c.MaxSens) { - pAC->I2c.CurrSens = 0; - Time = SK_I2C_TIM_LONG; - } - else { - Time = SK_I2C_TIM_SHORT; - } - - /* Start Timer */ - ParaLocal.Para64 = (SK_U64)0; - - pAC->I2c.TimerMode = SK_TIMER_NEW_GAUGING; - - SkTimerStart(pAC, IoC, &pAC->I2c.SenTimer, Time, - SKGE_I2C, SK_I2CEV_TIM, ParaLocal); - } - break; - case SK_I2CEV_CLEAR: - for (i = 0; i < SK_MAX_SENSORS; i++) { - pAC->I2c.SenTable[i].SenErrFlag = SK_SEN_ERR_OK; - pAC->I2c.SenTable[i].SenErrCts = 0; - pAC->I2c.SenTable[i].SenWarnCts = 0; - pAC->I2c.SenTable[i].SenBegErrTS = 0; - pAC->I2c.SenTable[i].SenBegWarnTS = 0; - pAC->I2c.SenTable[i].SenLastErrTrapTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastErrLogTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastWarnTrapTS = (SK_U64)0; - pAC->I2c.SenTable[i].SenLastWarnLogTS = (SK_U64)0; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E006, SKERR_I2C_E006MSG); - } - - return(0); -} /* SkI2cEvent*/ - -#endif /* !SK_DIAG */ diff --git a/drivers/net/sk98lin/sklm80.c b/drivers/net/sk98lin/sklm80.c deleted file mode 100644 index a204f5bb55d4..000000000000 --- a/drivers/net/sk98lin/sklm80.c +++ /dev/null @@ -1,141 +0,0 @@ -/****************************************************************************** - * - * Name: sklm80.c - * Project: Gigabit Ethernet Adapters, TWSI-Module - * Version: $Revision: 1.22 $ - * Date: $Date: 2003/10/20 09:08:21 $ - * Purpose: Functions to access Voltage and Temperature Sensor (LM80) - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - LM80 functions -*/ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: sklm80.c,v 1.22 2003/10/20 09:08:21 rschmidt Exp $ (C) Marvell. "; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/lm80.h" -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#define BREAK_OR_WAIT(pAC,IoC,Event) break - -/* - * read a sensors value (LM80 specific) - * - * This function reads a sensors value from the I2C sensor chip LM80. - * The sensor is defined by its index into the sensors database in the struct - * pAC points to. - * - * Returns 1 if the read is completed - * 0 if the read must be continued (I2C Bus still allocated) - */ -int SkLm80ReadSensor( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context needed in level 1 and 2 */ -SK_SENSOR *pSen) /* Sensor to be read */ -{ - SK_I32 Value; - - switch (pSen->SenState) { - case SK_SEN_IDLE: - /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, pSen->SenReg, 0); - - pSen->SenState = SK_SEN_VALUE ; - BREAK_OR_WAIT(pAC, IoC, I2C_READ); - - case SK_SEN_VALUE: - /* Read value from data register */ - SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); - - Value &= 0xff; /* only least significant byte is valid */ - - /* Do NOT check the Value against the thresholds */ - /* Checking is done in the calling instance */ - - if (pSen->SenType == SK_SEN_VOLT) { - /* Voltage sensor */ - pSen->SenValue = Value * SK_LM80_VT_LSB; - pSen->SenState = SK_SEN_IDLE ; - return(1); - } - - if (pSen->SenType == SK_SEN_FAN) { - if (Value != 0 && Value != 0xff) { - /* Fan speed counter */ - pSen->SenValue = SK_LM80_FAN_FAKTOR/Value; - } - else { - /* Indicate Fan error */ - pSen->SenValue = 0; - } - pSen->SenState = SK_SEN_IDLE ; - return(1); - } - - /* First: correct the value: it might be negative */ - if ((Value & 0x80) != 0) { - /* Value is negative */ - Value = Value - 256; - } - - /* We have a temperature sensor and need to get the signed extension. - * For now we get the extension from the last reading, so in the normal - * case we won't see flickering temperatures. - */ - pSen->SenValue = (Value * SK_LM80_TEMP_LSB) + - (pSen->SenValue % SK_LM80_TEMP_LSB); - - /* Send address to ADDR register */ - SK_I2C_CTL(IoC, I2C_READ, pSen->SenDev, I2C_025K_DEV, LM80_TEMP_CTRL, 0); - - pSen->SenState = SK_SEN_VALEXT ; - BREAK_OR_WAIT(pAC, IoC, I2C_READ); - - case SK_SEN_VALEXT: - /* Read value from data register */ - SK_IN32(IoC, B2_I2C_DATA, ((SK_U32 *)&Value)); - Value &= LM80_TEMP_LSB_9; /* only bit 7 is valid */ - - /* cut the LSB bit */ - pSen->SenValue = ((pSen->SenValue / SK_LM80_TEMP_LSB) * - SK_LM80_TEMP_LSB); - - if (pSen->SenValue < 0) { - /* Value negative: The bit value must be subtracted */ - pSen->SenValue -= ((Value >> 7) * SK_LM80_TEMPEXT_LSB); - } - else { - /* Value positive: The bit value must be added */ - pSen->SenValue += ((Value >> 7) * SK_LM80_TEMPEXT_LSB); - } - - pSen->SenState = SK_SEN_IDLE ; - return(1); - - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_I2C_E007, SKERR_I2C_E007MSG); - return(1); - } - - /* Not completed */ - return(0); -} - diff --git a/drivers/net/sk98lin/skqueue.c b/drivers/net/sk98lin/skqueue.c deleted file mode 100644 index 0275b4f71d9b..000000000000 --- a/drivers/net/sk98lin/skqueue.c +++ /dev/null @@ -1,179 +0,0 @@ -/****************************************************************************** - * - * Name: skqueue.c - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.20 $ - * Date: $Date: 2003/09/16 13:44:00 $ - * Purpose: Management of an event queue. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - - -/* - * Event queue and dispatcher - */ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skqueue.c,v 1.20 2003/09/16 13:44:00 rschmidt Exp $ (C) Marvell."; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skqueue.h" /* Queue Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - Event queue management. - - General Description: - - */ -intro() -{} -#endif - -#define PRINTF(a,b,c) - -/* - * init event queue management - * - * Must be called during init level 0. - */ -void SkEventInit( -SK_AC *pAC, /* Adapter context */ -SK_IOC Ioc, /* IO context */ -int Level) /* Init level */ -{ - switch (Level) { - case SK_INIT_DATA: - pAC->Event.EvPut = pAC->Event.EvGet = pAC->Event.EvQueue; - break; - default: - break; - } -} - -/* - * add event to queue - */ -void SkEventQueue( -SK_AC *pAC, /* Adapters context */ -SK_U32 Class, /* Event Class */ -SK_U32 Event, /* Event to be queued */ -SK_EVPARA Para) /* Event parameter */ -{ - pAC->Event.EvPut->Class = Class; - pAC->Event.EvPut->Event = Event; - pAC->Event.EvPut->Para = Para; - - if (++pAC->Event.EvPut == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pAC->Event.EvPut = pAC->Event.EvQueue; - - if (pAC->Event.EvPut == pAC->Event.EvGet) { - SK_ERR_LOG(pAC, SK_ERRCL_NORES, SKERR_Q_E001, SKERR_Q_E001MSG); - } -} - -/* - * event dispatcher - * while event queue is not empty - * get event from queue - * send command to state machine - * end - * return error reported by individual Event function - * 0 if no error occured. - */ -int SkEventDispatcher( -SK_AC *pAC, /* Adapters Context */ -SK_IOC Ioc) /* Io context */ -{ - SK_EVENTELEM *pEv; /* pointer into queue */ - SK_U32 Class; - int Rtv; - - pEv = pAC->Event.EvGet; - - PRINTF("dispatch get %x put %x\n", pEv, pAC->Event.ev_put); - - while (pEv != pAC->Event.EvPut) { - PRINTF("dispatch Class %d Event %d\n", pEv->Class, pEv->Event); - - switch (Class = pEv->Class) { -#ifndef SK_USE_LAC_EV -#ifndef SK_SLIM - case SKGE_RLMT: /* RLMT Event */ - Rtv = SkRlmtEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_I2C: /* I2C Event */ - Rtv = SkI2cEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_PNMI: /* PNMI Event */ - Rtv = SkPnmiEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#endif /* not SK_SLIM */ -#endif /* not SK_USE_LAC_EV */ - case SKGE_DRV: /* Driver Event */ - Rtv = SkDrvEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#ifndef SK_USE_SW_TIMER - case SKGE_HWAC: - Rtv = SkGeSirqEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#else /* !SK_USE_SW_TIMER */ - case SKGE_SWT : - Rtv = SkSwtEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#endif /* !SK_USE_SW_TIMER */ -#ifdef SK_USE_LAC_EV - case SKGE_LACP : - Rtv = SkLacpEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_RSF : - Rtv = SkRsfEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_MARKER : - Rtv = SkMarkerEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; - case SKGE_FD : - Rtv = SkFdEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#endif /* SK_USE_LAC_EV */ -#ifdef SK_USE_CSUM - case SKGE_CSUM : - Rtv = SkCsEvent(pAC, Ioc, pEv->Event, pEv->Para); - break; -#endif /* SK_USE_CSUM */ - default : - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_Q_E002, SKERR_Q_E002MSG); - Rtv = 0; - } - - if (Rtv != 0) { - return(Rtv); - } - - if (++pEv == &pAC->Event.EvQueue[SK_MAX_EVENT]) - pEv = pAC->Event.EvQueue; - - /* Renew get: it is used in queue_events to detect overruns */ - pAC->Event.EvGet = pEv; - } - - return(0); -} - -/* End of file */ diff --git a/drivers/net/sk98lin/skrlmt.c b/drivers/net/sk98lin/skrlmt.c deleted file mode 100644 index be8d1ccddf6d..000000000000 --- a/drivers/net/sk98lin/skrlmt.c +++ /dev/null @@ -1,3257 +0,0 @@ -/****************************************************************************** - * - * Name: skrlmt.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.69 $ - * Date: $Date: 2003/04/15 09:39:22 $ - * Purpose: Manage links on SK-NET Adapters, esp. redundant ones. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/****************************************************************************** - * - * Description: - * - * This module contains code for Link ManagemenT (LMT) of SK-NET Adapters. - * It is mainly intended for adapters with more than one link. - * For such adapters, this module realizes Redundant Link ManagemenT (RLMT). - * - * Include File Hierarchy: - * - * "skdrv1st.h" - * "skdrv2nd.h" - * - ******************************************************************************/ - -#ifndef lint -static const char SysKonnectFileId[] = - "@(#) $Id: skrlmt.c,v 1.69 2003/04/15 09:39:22 tschilli Exp $ (C) Marvell."; -#endif /* !defined(lint) */ - -#define __SKRLMT_C - -#ifdef __cplusplus -extern "C" { -#endif /* cplusplus */ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* defines ********************************************************************/ - -#ifndef SK_HWAC_LINK_LED -#define SK_HWAC_LINK_LED(a,b,c,d) -#endif /* !defined(SK_HWAC_LINK_LED) */ - -#ifndef DEBUG -#define RLMT_STATIC static -#else /* DEBUG */ -#define RLMT_STATIC - -#ifndef SK_LITTLE_ENDIAN -/* First 32 bits */ -#define OFFS_LO32 1 - -/* Second 32 bits */ -#define OFFS_HI32 0 -#else /* SK_LITTLE_ENDIAN */ -/* First 32 bits */ -#define OFFS_LO32 0 - -/* Second 32 bits */ -#define OFFS_HI32 1 -#endif /* SK_LITTLE_ENDIAN */ - -#endif /* DEBUG */ - -/* ----- Private timeout values ----- */ - -#define SK_RLMT_MIN_TO_VAL 125000 /* 1/8 sec. */ -#define SK_RLMT_DEF_TO_VAL 1000000 /* 1 sec. */ -#define SK_RLMT_PORTDOWN_TIM_VAL 900000 /* another 0.9 sec. */ -#define SK_RLMT_PORTSTART_TIM_VAL 100000 /* 0.1 sec. */ -#define SK_RLMT_PORTUP_TIM_VAL 2500000 /* 2.5 sec. */ -#define SK_RLMT_SEG_TO_VAL 900000000 /* 15 min. */ - -/* Assume tick counter increment is 1 - may be set OS-dependent. */ -#ifndef SK_TICK_INCR -#define SK_TICK_INCR SK_CONSTU64(1) -#endif /* !defined(SK_TICK_INCR) */ - -/* - * Amount that a time stamp must be later to be recognized as "substantially - * later". This is about 1/128 sec, but above 1 tick counter increment. - */ -#define SK_RLMT_BC_DELTA (1 + ((SK_TICKS_PER_SEC >> 7) > SK_TICK_INCR ? \ - (SK_TICKS_PER_SEC >> 7) : SK_TICK_INCR)) - -/* ----- Private RLMT defaults ----- */ - -#define SK_RLMT_DEF_PREF_PORT 0 /* "Lower" port. */ -#define SK_RLMT_DEF_MODE SK_RLMT_CHECK_LINK /* Default RLMT Mode. */ - -/* ----- Private RLMT checking states ----- */ - -#define SK_RLMT_RCS_SEG 1 /* RLMT Check State: check seg. */ -#define SK_RLMT_RCS_START_SEG 2 /* RLMT Check State: start check seg. */ -#define SK_RLMT_RCS_SEND_SEG 4 /* RLMT Check State: send BPDU packet */ -#define SK_RLMT_RCS_REPORT_SEG 8 /* RLMT Check State: report seg. */ - -/* ----- Private PORT checking states ----- */ - -#define SK_RLMT_PCS_TX 1 /* Port Check State: check tx. */ -#define SK_RLMT_PCS_RX 2 /* Port Check State: check rx. */ - -/* ----- Private PORT events ----- */ - -/* Note: Update simulation when changing these. */ -#define SK_RLMT_PORTSTART_TIM 1100 /* Port start timeout. */ -#define SK_RLMT_PORTUP_TIM 1101 /* Port can now go up. */ -#define SK_RLMT_PORTDOWN_RX_TIM 1102 /* Port did not receive once ... */ -#define SK_RLMT_PORTDOWN 1103 /* Port went down. */ -#define SK_RLMT_PORTDOWN_TX_TIM 1104 /* Partner did not receive ... */ - -/* ----- Private RLMT events ----- */ - -/* Note: Update simulation when changing these. */ -#define SK_RLMT_TIM 2100 /* RLMT timeout. */ -#define SK_RLMT_SEG_TIM 2101 /* RLMT segmentation check timeout. */ - -#define TO_SHORTEN(tim) ((tim) / 2) - -/* Error numbers and messages. */ -#define SKERR_RLMT_E001 (SK_ERRBASE_RLMT + 0) -#define SKERR_RLMT_E001_MSG "No Packet." -#define SKERR_RLMT_E002 (SKERR_RLMT_E001 + 1) -#define SKERR_RLMT_E002_MSG "Short Packet." -#define SKERR_RLMT_E003 (SKERR_RLMT_E002 + 1) -#define SKERR_RLMT_E003_MSG "Unknown RLMT event." -#define SKERR_RLMT_E004 (SKERR_RLMT_E003 + 1) -#define SKERR_RLMT_E004_MSG "PortsUp incorrect." -#define SKERR_RLMT_E005 (SKERR_RLMT_E004 + 1) -#define SKERR_RLMT_E005_MSG \ - "Net seems to be segmented (different root bridges are reported on the ports)." -#define SKERR_RLMT_E006 (SKERR_RLMT_E005 + 1) -#define SKERR_RLMT_E006_MSG "Duplicate MAC Address detected." -#define SKERR_RLMT_E007 (SKERR_RLMT_E006 + 1) -#define SKERR_RLMT_E007_MSG "LinksUp incorrect." -#define SKERR_RLMT_E008 (SKERR_RLMT_E007 + 1) -#define SKERR_RLMT_E008_MSG "Port not started but link came up." -#define SKERR_RLMT_E009 (SKERR_RLMT_E008 + 1) -#define SKERR_RLMT_E009_MSG "Corrected illegal setting of Preferred Port." -#define SKERR_RLMT_E010 (SKERR_RLMT_E009 + 1) -#define SKERR_RLMT_E010_MSG "Ignored illegal Preferred Port." - -/* LLC field values. */ -#define LLC_COMMAND_RESPONSE_BIT 1 -#define LLC_TEST_COMMAND 0xE3 -#define LLC_UI 0x03 - -/* RLMT Packet fields. */ -#define SK_RLMT_DSAP 0 -#define SK_RLMT_SSAP 0 -#define SK_RLMT_CTRL (LLC_TEST_COMMAND) -#define SK_RLMT_INDICATOR0 0x53 /* S */ -#define SK_RLMT_INDICATOR1 0x4B /* K */ -#define SK_RLMT_INDICATOR2 0x2D /* - */ -#define SK_RLMT_INDICATOR3 0x52 /* R */ -#define SK_RLMT_INDICATOR4 0x4C /* L */ -#define SK_RLMT_INDICATOR5 0x4D /* M */ -#define SK_RLMT_INDICATOR6 0x54 /* T */ -#define SK_RLMT_PACKET_VERSION 0 - -/* RLMT SPT Flag values. */ -#define SK_RLMT_SPT_FLAG_CHANGE 0x01 -#define SK_RLMT_SPT_FLAG_CHANGE_ACK 0x80 - -/* RLMT SPT Packet fields. */ -#define SK_RLMT_SPT_DSAP 0x42 -#define SK_RLMT_SPT_SSAP 0x42 -#define SK_RLMT_SPT_CTRL (LLC_UI) -#define SK_RLMT_SPT_PROTOCOL_ID0 0x00 -#define SK_RLMT_SPT_PROTOCOL_ID1 0x00 -#define SK_RLMT_SPT_PROTOCOL_VERSION_ID 0x00 -#define SK_RLMT_SPT_BPDU_TYPE 0x00 -#define SK_RLMT_SPT_FLAGS 0x00 /* ?? */ -#define SK_RLMT_SPT_ROOT_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_ROOT_ID1 0xFF /* Lowest possible priority. */ - -/* Remaining 6 bytes will be the current port address. */ -#define SK_RLMT_SPT_ROOT_PATH_COST0 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST1 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST2 0x00 -#define SK_RLMT_SPT_ROOT_PATH_COST3 0x00 -#define SK_RLMT_SPT_BRIDGE_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_BRIDGE_ID1 0xFF /* Lowest possible priority. */ - -/* Remaining 6 bytes will be the current port address. */ -#define SK_RLMT_SPT_PORT_ID0 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_PORT_ID1 0xFF /* Lowest possible priority. */ -#define SK_RLMT_SPT_MSG_AGE0 0x00 -#define SK_RLMT_SPT_MSG_AGE1 0x00 -#define SK_RLMT_SPT_MAX_AGE0 0x00 -#define SK_RLMT_SPT_MAX_AGE1 0xFF -#define SK_RLMT_SPT_HELLO_TIME0 0x00 -#define SK_RLMT_SPT_HELLO_TIME1 0xFF -#define SK_RLMT_SPT_FWD_DELAY0 0x00 -#define SK_RLMT_SPT_FWD_DELAY1 0x40 - -/* Size defines. */ -#define SK_RLMT_MIN_PACKET_SIZE 34 -#define SK_RLMT_MAX_PACKET_SIZE (SK_RLMT_MAX_TX_BUF_SIZE) -#define SK_PACKET_DATA_LEN (SK_RLMT_MAX_PACKET_SIZE - \ - SK_RLMT_MIN_PACKET_SIZE) - -/* ----- RLMT packet types ----- */ -#define SK_PACKET_ANNOUNCE 1 /* Port announcement. */ -#define SK_PACKET_ALIVE 2 /* Alive packet to port. */ -#define SK_PACKET_ADDR_CHANGED 3 /* Port address changed. */ -#define SK_PACKET_CHECK_TX 4 /* Check your tx line. */ - -#ifdef SK_LITTLE_ENDIAN -#define SK_U16_TO_NETWORK_ORDER(Val,Addr) { \ - SK_U8 *_Addr = (SK_U8*)(Addr); \ - SK_U16 _Val = (SK_U16)(Val); \ - *_Addr++ = (SK_U8)(_Val >> 8); \ - *_Addr = (SK_U8)(_Val & 0xFF); \ -} -#endif /* SK_LITTLE_ENDIAN */ - -#ifdef SK_BIG_ENDIAN -#define SK_U16_TO_NETWORK_ORDER(Val,Addr) (*(SK_U16*)(Addr) = (SK_U16)(Val)) -#endif /* SK_BIG_ENDIAN */ - -#define AUTONEG_FAILED SK_FALSE -#define AUTONEG_SUCCESS SK_TRUE - - -/* typedefs *******************************************************************/ - -/* RLMT packet. Length: SK_RLMT_MAX_PACKET_SIZE (60) bytes. */ -typedef struct s_RlmtPacket { - SK_U8 DstAddr[SK_MAC_ADDR_LEN]; - SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; - SK_U8 TypeLen[2]; - SK_U8 DSap; - SK_U8 SSap; - SK_U8 Ctrl; - SK_U8 Indicator[7]; - SK_U8 RlmtPacketType[2]; - SK_U8 Align1[2]; - SK_U8 Random[4]; /* Random value of requesting(!) station. */ - SK_U8 RlmtPacketVersion[2]; /* RLMT Packet version. */ - SK_U8 Data[SK_PACKET_DATA_LEN]; -} SK_RLMT_PACKET; - -typedef struct s_SpTreeRlmtPacket { - SK_U8 DstAddr[SK_MAC_ADDR_LEN]; - SK_U8 SrcAddr[SK_MAC_ADDR_LEN]; - SK_U8 TypeLen[2]; - SK_U8 DSap; - SK_U8 SSap; - SK_U8 Ctrl; - SK_U8 ProtocolId[2]; - SK_U8 ProtocolVersionId; - SK_U8 BpduType; - SK_U8 Flags; - SK_U8 RootId[8]; - SK_U8 RootPathCost[4]; - SK_U8 BridgeId[8]; - SK_U8 PortId[2]; - SK_U8 MessageAge[2]; - SK_U8 MaxAge[2]; - SK_U8 HelloTime[2]; - SK_U8 ForwardDelay[2]; -} SK_SPTREE_PACKET; - -/* global variables ***********************************************************/ - -SK_MAC_ADDR SkRlmtMcAddr = {{0x01, 0x00, 0x5A, 0x52, 0x4C, 0x4D}}; -SK_MAC_ADDR BridgeMcAddr = {{0x01, 0x80, 0xC2, 0x00, 0x00, 0x00}}; - -/* local variables ************************************************************/ - -/* None. */ - -/* functions ******************************************************************/ - -RLMT_STATIC void SkRlmtCheckSwitch( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 NetIdx); -RLMT_STATIC void SkRlmtCheckSeg( - SK_AC *pAC, - SK_IOC IoC, - SK_U32 NetIdx); -RLMT_STATIC void SkRlmtEvtSetNets( - SK_AC *pAC, - SK_IOC IoC, - SK_EVPARA Para); - -/****************************************************************************** - * - * SkRlmtInit - initialize data, set state to init - * - * Description: - * - * SK_INIT_DATA - * ============ - * - * This routine initializes all RLMT-related variables to a known state. - * The initial state is SK_RLMT_RS_INIT. - * All ports are initialized to SK_RLMT_PS_INIT. - * - * - * SK_INIT_IO - * ========== - * - * Nothing. - * - * - * SK_INIT_RUN - * =========== - * - * Determine the adapter's random value. - * Set the hw registers, the "logical MAC address", the - * RLMT multicast address, and eventually the BPDU multicast address. - * - * Context: - * init, pageable - * - * Returns: - * Nothing. - */ -void SkRlmtInit( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Level) /* Initialization Level */ -{ - SK_U32 i, j; - SK_U64 Random; - SK_EVPARA Para; - SK_MAC_ADDR VirtualMacAddress; - SK_MAC_ADDR PhysicalAMacAddress; - SK_BOOL VirtualMacAddressSet; - SK_BOOL PhysicalAMacAddressSet; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, - ("RLMT Init level %d.\n", Level)) - - switch (Level) { - case SK_INIT_DATA: /* Initialize data structures. */ - SK_MEMSET((char *)&pAC->Rlmt, 0, sizeof(SK_RLMT)); - - for (i = 0; i < SK_MAX_MACS; i++) { - pAC->Rlmt.Port[i].PortState = SK_RLMT_PS_INIT; - pAC->Rlmt.Port[i].LinkDown = SK_TRUE; - pAC->Rlmt.Port[i].PortDown = SK_TRUE; - pAC->Rlmt.Port[i].PortStarted = SK_FALSE; - pAC->Rlmt.Port[i].PortNoRx = SK_FALSE; - pAC->Rlmt.Port[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Port[i].PortNumber = i; - pAC->Rlmt.Port[i].Net = &pAC->Rlmt.Net[0]; - pAC->Rlmt.Port[i].AddrPort = &pAC->Addr.Port[i]; - } - - pAC->Rlmt.NumNets = 1; - for (i = 0; i < SK_MAX_NETS; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* Automatic. */ - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - pAC->Rlmt.Net[i].NetNumber = i; - } - - pAC->Rlmt.Net[0].Port[0] = &pAC->Rlmt.Port[0]; - pAC->Rlmt.Net[0].Port[1] = &pAC->Rlmt.Port[1]; -#if SK_MAX_NETS > 1 - pAC->Rlmt.Net[1].Port[0] = &pAC->Rlmt.Port[1]; -#endif /* SK_MAX_NETS > 1 */ - break; - - case SK_INIT_IO: /* GIMacsFound first available here. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_INIT, - ("RLMT: %d MACs were detected.\n", pAC->GIni.GIMacsFound)) - - pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; - - /* Initialize HW registers? */ - if (pAC->GIni.GIMacsFound == 1) { - Para.Para32[0] = SK_RLMT_MODE_CLS; - Para.Para32[1] = 0; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_MODE_CHANGE, Para); - } - break; - - case SK_INIT_RUN: - /* Ensure RLMT is set to one net. */ - if (pAC->Rlmt.NumNets > 1) { - Para.Para32[0] = 1; - Para.Para32[1] = -1; - SkRlmtEvtSetNets(pAC, IoC, Para); - } - - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - Random = SkOsGetTime(pAC); - *(SK_U32*)&pAC->Rlmt.Port[i].Random = *(SK_U32*)&Random; - - for (j = 0; j < 4; j++) { - pAC->Rlmt.Port[i].Random[j] ^= pAC->Rlmt.Port[i].AddrPort-> - CurrentMacAddress.a[SK_MAC_ADDR_LEN - 1 - j]; - } - - (void)SkAddrMcClear(pAC, IoC, i, SK_ADDR_PERMANENT | SK_MC_SW_ONLY); - - /* Add RLMT MC address. */ - (void)SkAddrMcAdd(pAC, IoC, i, &SkRlmtMcAddr, SK_ADDR_PERMANENT); - - if (pAC->Rlmt.Net[0].RlmtMode & SK_RLMT_CHECK_SEG) { - /* Add BPDU MC address. */ - (void)SkAddrMcAdd(pAC, IoC, i, &BridgeMcAddr, SK_ADDR_PERMANENT); - } - - (void)SkAddrMcUpdate(pAC, IoC, i); - } - - VirtualMacAddressSet = SK_FALSE; - /* Read virtual MAC address from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - - SK_IN8(IoC, B2_MAC_1 + j, &VirtualMacAddress.a[j]); - VirtualMacAddressSet |= VirtualMacAddress.a[j]; - } - - PhysicalAMacAddressSet = SK_FALSE; - /* Read physical MAC address for MAC A from Control Register File. */ - for (j = 0; j < SK_MAC_ADDR_LEN; j++) { - - SK_IN8(IoC, B2_MAC_2 + j, &PhysicalAMacAddress.a[j]); - PhysicalAMacAddressSet |= PhysicalAMacAddress.a[j]; - } - - /* check if the two mac addresses contain reasonable values */ - if (!VirtualMacAddressSet || !PhysicalAMacAddressSet) { - - pAC->Rlmt.RlmtOff = SK_TRUE; - } - - /* if the two mac addresses are equal switch off the RLMT_PRE_LOOKAHEAD - and the RLMT_LOOKAHEAD macros */ - else if (SK_ADDR_EQUAL(PhysicalAMacAddress.a, VirtualMacAddress.a)) { - - pAC->Rlmt.RlmtOff = SK_TRUE; - } - else { - pAC->Rlmt.RlmtOff = SK_FALSE; - } - break; - - default: /* error */ - break; - } - return; -} /* SkRlmtInit */ - - -/****************************************************************************** - * - * SkRlmtBuildCheckChain - build the check chain - * - * Description: - * This routine builds the local check chain: - * - Each port that is up checks the next port. - * - The last port that is up checks the first port that is up. - * - * Notes: - * - Currently only local ports are considered when building the chain. - * - Currently the SuspectState is just reset; - * it would be better to save it ... - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtBuildCheckChain( -SK_AC *pAC, /* Adapter Context */ -SK_U32 NetIdx) /* Net Number */ -{ - SK_U32 i; - SK_U32 NumMacsUp; - SK_RLMT_PORT * FirstMacUp; - SK_RLMT_PORT * PrevMacUp; - - FirstMacUp = NULL; - PrevMacUp = NULL; - - if (!(pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { - for (i = 0; i < pAC->Rlmt.Net[i].NumPorts; i++) { - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; - } - return; /* Done. */ - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtBuildCheckChain.\n")) - - NumMacsUp = 0; - - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked = 0; - pAC->Rlmt.Net[NetIdx].Port[i]->PortsSuspect = 0; - pAC->Rlmt.Net[NetIdx].Port[i]->CheckingState &= - ~(SK_RLMT_PCS_RX | SK_RLMT_PCS_TX); - - /* - * If more than two links are detected we should consider - * checking at least two other ports: - * 1. the next port that is not LinkDown and - * 2. the next port that is not PortDown. - */ - if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { - if (NumMacsUp == 0) { - FirstMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; - } - else { - PrevMacUp->PortCheck[ - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked].CheckAddr = - pAC->Rlmt.Net[NetIdx].Port[i]->AddrPort->CurrentMacAddress; - PrevMacUp->PortCheck[ - PrevMacUp->PortsChecked].SuspectTx = SK_FALSE; - PrevMacUp->PortsChecked++; - } - PrevMacUp = pAC->Rlmt.Net[NetIdx].Port[i]; - NumMacsUp++; - } - } - - if (NumMacsUp > 1) { - PrevMacUp->PortCheck[PrevMacUp->PortsChecked].CheckAddr = - FirstMacUp->AddrPort->CurrentMacAddress; - PrevMacUp->PortCheck[PrevMacUp->PortsChecked].SuspectTx = - SK_FALSE; - PrevMacUp->PortsChecked++; - } - -#ifdef DEBUG - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d checks %d other ports: %2X.\n", i, - pAC->Rlmt.Net[NetIdx].Port[i]->PortsChecked, - pAC->Rlmt.Net[NetIdx].Port[i]->PortCheck[0].CheckAddr.a[5])) - } -#endif /* DEBUG */ - - return; -} /* SkRlmtBuildCheckChain */ - - -/****************************************************************************** - * - * SkRlmtBuildPacket - build an RLMT packet - * - * Description: - * This routine sets up an RLMT packet. - * - * Context: - * runtime, pageable? - * - * Returns: - * NULL or pointer to RLMT mbuf - */ -RLMT_STATIC SK_MBUF *SkRlmtBuildPacket( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber, /* Sending port */ -SK_U16 PacketType, /* RLMT packet type */ -SK_MAC_ADDR *SrcAddr, /* Source address */ -SK_MAC_ADDR *DestAddr) /* Destination address */ -{ - int i; - SK_U16 Length; - SK_MBUF *pMb; - SK_RLMT_PACKET *pPacket; - -#ifdef DEBUG - SK_U8 CheckSrc = 0; - SK_U8 CheckDest = 0; - - for (i = 0; i < SK_MAC_ADDR_LEN; ++i) { - CheckSrc |= SrcAddr->a[i]; - CheckDest |= DestAddr->a[i]; - } - - if ((CheckSrc == 0) || (CheckDest == 0)) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_ERR, - ("SkRlmtBuildPacket: Invalid %s%saddr.\n", - (CheckSrc == 0 ? "Src" : ""), (CheckDest == 0 ? "Dest" : ""))) - } -#endif - - if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != NULL) { - pPacket = (SK_RLMT_PACKET*)pMb->pData; - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pPacket->DstAddr[i] = DestAddr->a[i]; - pPacket->SrcAddr[i] = SrcAddr->a[i]; - } - pPacket->DSap = SK_RLMT_DSAP; - pPacket->SSap = SK_RLMT_SSAP; - pPacket->Ctrl = SK_RLMT_CTRL; - pPacket->Indicator[0] = SK_RLMT_INDICATOR0; - pPacket->Indicator[1] = SK_RLMT_INDICATOR1; - pPacket->Indicator[2] = SK_RLMT_INDICATOR2; - pPacket->Indicator[3] = SK_RLMT_INDICATOR3; - pPacket->Indicator[4] = SK_RLMT_INDICATOR4; - pPacket->Indicator[5] = SK_RLMT_INDICATOR5; - pPacket->Indicator[6] = SK_RLMT_INDICATOR6; - - SK_U16_TO_NETWORK_ORDER(PacketType, &pPacket->RlmtPacketType[0]); - - for (i = 0; i < 4; i++) { - pPacket->Random[i] = pAC->Rlmt.Port[PortNumber].Random[i]; - } - - SK_U16_TO_NETWORK_ORDER( - SK_RLMT_PACKET_VERSION, &pPacket->RlmtPacketVersion[0]); - - for (i = 0; i < SK_PACKET_DATA_LEN; i++) { - pPacket->Data[i] = 0x00; - } - - Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ - pMb->Length = Length; - pMb->PortIdx = PortNumber; - Length -= 14; - SK_U16_TO_NETWORK_ORDER(Length, &pPacket->TypeLen[0]); - - if (PacketType == SK_PACKET_ALIVE) { - pAC->Rlmt.Port[PortNumber].TxHelloCts++; - } - } - - return (pMb); -} /* SkRlmtBuildPacket */ - - -/****************************************************************************** - * - * SkRlmtBuildSpanningTreePacket - build spanning tree check packet - * - * Description: - * This routine sets up a BPDU packet for spanning tree check. - * - * Context: - * runtime, pageable? - * - * Returns: - * NULL or pointer to RLMT mbuf - */ -RLMT_STATIC SK_MBUF *SkRlmtBuildSpanningTreePacket( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Sending port */ -{ - unsigned i; - SK_U16 Length; - SK_MBUF *pMb; - SK_SPTREE_PACKET *pSPacket; - - if ((pMb = SkDrvAllocRlmtMbuf(pAC, IoC, SK_RLMT_MAX_PACKET_SIZE)) != - NULL) { - pSPacket = (SK_SPTREE_PACKET*)pMb->pData; - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pSPacket->DstAddr[i] = BridgeMcAddr.a[i]; - pSPacket->SrcAddr[i] = - pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; - } - pSPacket->DSap = SK_RLMT_SPT_DSAP; - pSPacket->SSap = SK_RLMT_SPT_SSAP; - pSPacket->Ctrl = SK_RLMT_SPT_CTRL; - - pSPacket->ProtocolId[0] = SK_RLMT_SPT_PROTOCOL_ID0; - pSPacket->ProtocolId[1] = SK_RLMT_SPT_PROTOCOL_ID1; - pSPacket->ProtocolVersionId = SK_RLMT_SPT_PROTOCOL_VERSION_ID; - pSPacket->BpduType = SK_RLMT_SPT_BPDU_TYPE; - pSPacket->Flags = SK_RLMT_SPT_FLAGS; - pSPacket->RootId[0] = SK_RLMT_SPT_ROOT_ID0; - pSPacket->RootId[1] = SK_RLMT_SPT_ROOT_ID1; - pSPacket->RootPathCost[0] = SK_RLMT_SPT_ROOT_PATH_COST0; - pSPacket->RootPathCost[1] = SK_RLMT_SPT_ROOT_PATH_COST1; - pSPacket->RootPathCost[2] = SK_RLMT_SPT_ROOT_PATH_COST2; - pSPacket->RootPathCost[3] = SK_RLMT_SPT_ROOT_PATH_COST3; - pSPacket->BridgeId[0] = SK_RLMT_SPT_BRIDGE_ID0; - pSPacket->BridgeId[1] = SK_RLMT_SPT_BRIDGE_ID1; - - /* - * Use logical MAC address as bridge ID and filter these packets - * on receive. - */ - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pSPacket->BridgeId[i + 2] = pSPacket->RootId[i + 2] = - pAC->Addr.Net[pAC->Rlmt.Port[PortNumber].Net->NetNumber]. - CurrentMacAddress.a[i]; - } - pSPacket->PortId[0] = SK_RLMT_SPT_PORT_ID0; - pSPacket->PortId[1] = SK_RLMT_SPT_PORT_ID1; - pSPacket->MessageAge[0] = SK_RLMT_SPT_MSG_AGE0; - pSPacket->MessageAge[1] = SK_RLMT_SPT_MSG_AGE1; - pSPacket->MaxAge[0] = SK_RLMT_SPT_MAX_AGE0; - pSPacket->MaxAge[1] = SK_RLMT_SPT_MAX_AGE1; - pSPacket->HelloTime[0] = SK_RLMT_SPT_HELLO_TIME0; - pSPacket->HelloTime[1] = SK_RLMT_SPT_HELLO_TIME1; - pSPacket->ForwardDelay[0] = SK_RLMT_SPT_FWD_DELAY0; - pSPacket->ForwardDelay[1] = SK_RLMT_SPT_FWD_DELAY1; - - Length = SK_RLMT_MAX_PACKET_SIZE; /* Or smaller. */ - pMb->Length = Length; - pMb->PortIdx = PortNumber; - Length -= 14; - SK_U16_TO_NETWORK_ORDER(Length, &pSPacket->TypeLen[0]); - - pAC->Rlmt.Port[PortNumber].TxSpHelloReqCts++; - } - - return (pMb); -} /* SkRlmtBuildSpanningTreePacket */ - - -/****************************************************************************** - * - * SkRlmtSend - build and send check packets - * - * Description: - * Depending on the RLMT state and the checking state, several packets - * are sent through the indicated port. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtSend( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Sending port */ -{ - unsigned j; - SK_EVPARA Para; - SK_RLMT_PORT *pRPort; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - if (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { - if (pRPort->CheckingState & (SK_RLMT_PCS_TX | SK_RLMT_PCS_RX)) { - /* Port is suspicious. Send the RLMT packet to the RLMT mc addr. */ - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - else { - /* - * Send a directed RLMT packet to all ports that are - * checked by the indicated port. - */ - for (j = 0; j < pRPort->PortsChecked; j++) { - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &pRPort->PortCheck[j].CheckAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - } - } - - if ((pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && - (pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEND_SEG)) { - /* - * Send a BPDU packet to make a connected switch tell us - * the correct root bridge. - */ - if ((Para.pParaPtr = - SkRlmtBuildSpanningTreePacket(pAC, IoC, PortNumber)) != NULL) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState &= ~SK_RLMT_RCS_SEND_SEG; - pRPort->RootIdSet = SK_FALSE; - - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_TX, - ("SkRlmtSend: BPDU Packet on Port %u.\n", PortNumber)) - } - } - return; -} /* SkRlmtSend */ - - -/****************************************************************************** - * - * SkRlmtPortReceives - check if port is (going) down and bring it up - * - * Description: - * This routine checks if a port who received a non-BPDU packet - * needs to go up or needs to be stopped going down. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtPortReceives( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port to check */ -{ - SK_RLMT_PORT *pRPort; - SK_EVPARA Para; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - pRPort->PortNoRx = SK_FALSE; - - if ((pRPort->PortState == SK_RLMT_PS_DOWN) && - !(pRPort->CheckingState & SK_RLMT_PCS_TX)) { - /* - * Port is marked down (rx), but received a non-BPDU packet. - * Bring it up. - */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Received on PortDown.\n")) - - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, - SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para); - pRPort->CheckingState &= ~SK_RLMT_PCS_RX; - /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } /* PortDown && !SuspectTx */ - else if (pRPort->CheckingState & SK_RLMT_PCS_RX) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Stop bringing port down.\n")) - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - pRPort->CheckingState &= ~SK_RLMT_PCS_RX; - /* pAC->Rlmt.CheckSwitch = SK_TRUE; */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } /* PortGoingDown */ - - return; -} /* SkRlmtPortReceives */ - - -/****************************************************************************** - * - * SkRlmtPacketReceive - receive a packet for closer examination - * - * Description: - * This routine examines a packet more closely than SK_RLMT_LOOKAHEAD. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtPacketReceive( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_MBUF *pMb) /* Received packet */ -{ -#ifdef xDEBUG - extern void DumpData(char *p, int size); -#endif /* DEBUG */ - int i; - unsigned j; - SK_U16 PacketType; - SK_U32 PortNumber; - SK_ADDR_PORT *pAPort; - SK_RLMT_PORT *pRPort; - SK_RLMT_PACKET *pRPacket; - SK_SPTREE_PACKET *pSPacket; - SK_EVPARA Para; - - PortNumber = pMb->PortIdx; - pAPort = &pAC->Addr.Port[PortNumber]; - pRPort = &pAC->Rlmt.Port[PortNumber]; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: PortNumber == %d.\n", PortNumber)) - - pRPacket = (SK_RLMT_PACKET*)pMb->pData; - pSPacket = (SK_SPTREE_PACKET*)pRPacket; - -#ifdef xDEBUG - DumpData((char *)pRPacket, 32); -#endif /* DEBUG */ - - if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) != 0) { - SkRlmtPortReceives(pAC, IoC, PortNumber); - } - - /* Check destination address. */ - - if (!SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->DstAddr) && - !SK_ADDR_EQUAL(SkRlmtMcAddr.a, pRPacket->DstAddr) && - !SK_ADDR_EQUAL(BridgeMcAddr.a, pRPacket->DstAddr)) { - - /* Not sent to current MAC or registered MC address => Trash it. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Not for me.\n")) - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - return; - } - else if (SK_ADDR_EQUAL(pAPort->CurrentMacAddress.a, pRPacket->SrcAddr)) { - - /* - * Was sent by same port (may happen during port switching - * or in case of duplicate MAC addresses). - */ - - /* - * Check for duplicate address here: - * If Packet.Random != My.Random => DupAddr. - */ - for (i = 3; i >= 0; i--) { - if (pRPort->Random[i] != pRPacket->Random[i]) { - break; - } - } - - /* - * CAUTION: Do not check for duplicate MAC address in RLMT Alive Reply - * packets (they have the LLC_COMMAND_RESPONSE_BIT set in - * pRPacket->SSap). - */ - if (i >= 0 && pRPacket->DSap == SK_RLMT_DSAP && - pRPacket->Ctrl == SK_RLMT_CTRL && - pRPacket->SSap == SK_RLMT_SSAP && - pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && - pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && - pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && - pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && - pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && - pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && - pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Duplicate MAC Address.\n")) - - /* Error Log entry. */ - SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E006, SKERR_RLMT_E006_MSG); - } - else { - /* Simply trash it. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Sent by me.\n")) - } - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - return; - } - - /* Check SuspectTx entries. */ - if (pRPort->PortsSuspect > 0) { - for (j = 0; j < pRPort->PortsChecked; j++) { - if (pRPort->PortCheck[j].SuspectTx && - SK_ADDR_EQUAL( - pRPacket->SrcAddr, pRPort->PortCheck[j].CheckAddr.a)) { - pRPort->PortCheck[j].SuspectTx = SK_FALSE; - pRPort->PortsSuspect--; - break; - } - } - } - - /* Determine type of packet. */ - if (pRPacket->DSap == SK_RLMT_DSAP && - pRPacket->Ctrl == SK_RLMT_CTRL && - (pRPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SSAP && - pRPacket->Indicator[0] == SK_RLMT_INDICATOR0 && - pRPacket->Indicator[1] == SK_RLMT_INDICATOR1 && - pRPacket->Indicator[2] == SK_RLMT_INDICATOR2 && - pRPacket->Indicator[3] == SK_RLMT_INDICATOR3 && - pRPacket->Indicator[4] == SK_RLMT_INDICATOR4 && - pRPacket->Indicator[5] == SK_RLMT_INDICATOR5 && - pRPacket->Indicator[6] == SK_RLMT_INDICATOR6) { - - /* It's an RLMT packet. */ - PacketType = (SK_U16)((pRPacket->RlmtPacketType[0] << 8) | - pRPacket->RlmtPacketType[1]); - - switch (PacketType) { - case SK_PACKET_ANNOUNCE: /* Not yet used. */ -#if 0 - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC); -#endif /* 0 */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Announce.\n")) - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - break; - - case SK_PACKET_ALIVE: - if (pRPacket->SSap & LLC_COMMAND_RESPONSE_BIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Alive Reply.\n")) - - if (!(pAC->Addr.Port[PortNumber].PromMode & SK_PROM_MODE_LLC) || - SK_ADDR_EQUAL( - pRPacket->DstAddr, pAPort->CurrentMacAddress.a)) { - /* Obviously we could send something. */ - if (pRPort->CheckingState & SK_RLMT_PCS_TX) { - pRPort->CheckingState &= ~SK_RLMT_PCS_TX; - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - } - - if ((pRPort->PortState == SK_RLMT_PS_DOWN) && - !(pRPort->CheckingState & SK_RLMT_PCS_RX)) { - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, - SK_RLMT_PORTUP_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTUP_TIM, Para); - } - } - - /* Mark sending port as alive? */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - else { /* Alive Request Packet. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Alive Request.\n")) - - pRPort->RxHelloCts++; - - /* Answer. */ - for (i = 0; i < SK_MAC_ADDR_LEN; i++) { - pRPacket->DstAddr[i] = pRPacket->SrcAddr[i]; - pRPacket->SrcAddr[i] = - pAC->Addr.Port[PortNumber].CurrentMacAddress.a[i]; - } - pRPacket->SSap |= LLC_COMMAND_RESPONSE_BIT; - - Para.pParaPtr = pMb; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - break; - - case SK_PACKET_CHECK_TX: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Check your tx line.\n")) - - /* A port checking us requests us to check our tx line. */ - pRPort->CheckingState |= SK_RLMT_PCS_TX; - - /* Start PortDownTx timer. */ - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->DownTxTimer, - SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTDOWN_TX_TIM, Para); - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - - if ((Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, PortNumber, - SK_PACKET_ALIVE, &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - break; - - case SK_PACKET_ADDR_CHANGED: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Address Change.\n")) - - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - break; - - default: - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Unknown RLMT packet.\n")) - - /* RA;:;: ??? */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - } - else if (pSPacket->DSap == SK_RLMT_SPT_DSAP && - pSPacket->Ctrl == SK_RLMT_SPT_CTRL && - (pSPacket->SSap & ~LLC_COMMAND_RESPONSE_BIT) == SK_RLMT_SPT_SSAP) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: BPDU Packet.\n")) - - /* Spanning Tree packet. */ - pRPort->RxSpHelloCts++; - - if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pAC->Addr.Net[pAC->Rlmt. - Port[PortNumber].Net->NetNumber].CurrentMacAddress.a[0])) { - /* - * Check segmentation if a new root bridge is set and - * the segmentation check is not currently running. - */ - if (!SK_ADDR_EQUAL(&pSPacket->RootId[2], &pRPort->Root.Id[2]) && - (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && - (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) - != 0 && (pAC->Rlmt.Port[PortNumber].Net->CheckingState & - SK_RLMT_RCS_SEG) == 0) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState |= - SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; - } - - /* Store tree view of this port. */ - for (i = 0; i < 8; i++) { - pRPort->Root.Id[i] = pSPacket->RootId[i]; - } - pRPort->RootIdSet = SK_TRUE; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, - ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", - PortNumber, - pRPort->Root.Id[0], pRPort->Root.Id[1], - pRPort->Root.Id[2], pRPort->Root.Id[3], - pRPort->Root.Id[4], pRPort->Root.Id[5], - pRPort->Root.Id[6], pRPort->Root.Id[7])) - } - - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - if ((pAC->Rlmt.Port[PortNumber].Net->CheckingState & - SK_RLMT_RCS_REPORT_SEG) != 0) { - SkRlmtCheckSeg(pAC, IoC, pAC->Rlmt.Port[PortNumber].Net->NetNumber); - } - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_RX, - ("SkRlmtPacketReceive: Unknown Packet Type.\n")) - - /* Unknown packet. */ - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - return; -} /* SkRlmtPacketReceive */ - - -/****************************************************************************** - * - * SkRlmtCheckPort - check if a port works - * - * Description: - * This routine checks if a port whose link is up received something - * and if it seems to transmit successfully. - * - * # PortState: PsInit, PsLinkDown, PsDown, PsGoingUp, PsUp - * # PortCheckingState (Bitfield): ChkTx, ChkRx, ChkSeg - * # RlmtCheckingState (Bitfield): ChkSeg, StartChkSeg, ReportSeg - * - * if (Rx - RxBpdu == 0) { # No rx. - * if (state == PsUp) { - * PortCheckingState |= ChkRx - * } - * if (ModeCheckSeg && (Timeout == - * TO_SHORTEN(RLMT_DEFAULT_TIMEOUT))) { - * RlmtCheckingState |= ChkSeg) - * PortCheckingState |= ChkSeg - * } - * NewTimeout = TO_SHORTEN(Timeout) - * if (NewTimeout < RLMT_MIN_TIMEOUT) { - * NewTimeout = RLMT_MIN_TIMEOUT - * PortState = PsDown - * ... - * } - * } - * else { # something was received - * # Set counter to 0 at LinkDown? - * # No - rx may be reported after LinkDown ??? - * PortCheckingState &= ~ChkRx - * NewTimeout = RLMT_DEFAULT_TIMEOUT - * if (RxAck == 0) { - * possible reasons: - * is my tx line bad? -- - * send RLMT multicast and report - * back internally? (only possible - * between ports on same adapter) - * } - * if (RxChk == 0) { - * possible reasons: - * - tx line of port set to check me - * maybe bad - * - no other port/adapter available or set - * to check me - * - adapter checking me has a longer - * timeout - * ??? anything that can be done here? - * } - * } - * - * Context: - * runtime, pageable? - * - * Returns: - * New timeout value. - */ -RLMT_STATIC SK_U32 SkRlmtCheckPort( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port to check */ -{ - unsigned i; - SK_U32 NewTimeout; - SK_RLMT_PORT *pRPort; - SK_EVPARA Para; - - pRPort = &pAC->Rlmt.Port[PortNumber]; - - if ((pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot) == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort %d: No (%d) receives in last time slot.\n", - PortNumber, pRPort->PacketsPerTimeSlot)) - - /* - * Check segmentation if there was no receive at least twice - * in a row (PortNoRx is already set) and the segmentation - * check is not currently running. - */ - - if (pRPort->PortNoRx && (pAC->Rlmt.Port[PortNumber].Net->LinksUp > 1) && - (pAC->Rlmt.Port[PortNumber].Net->RlmtMode & SK_RLMT_CHECK_SEG) && - !(pAC->Rlmt.Port[PortNumber].Net->CheckingState & SK_RLMT_RCS_SEG)) { - pAC->Rlmt.Port[PortNumber].Net->CheckingState |= - SK_RLMT_RCS_START_SEG | SK_RLMT_RCS_SEND_SEG; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort: PortsSuspect %d, PcsRx %d.\n", - pRPort->PortsSuspect, pRPort->CheckingState & SK_RLMT_PCS_RX)) - - if (pRPort->PortState != SK_RLMT_PS_DOWN) { - NewTimeout = TO_SHORTEN(pAC->Rlmt.Port[PortNumber].Net->TimeoutValue); - if (NewTimeout < SK_RLMT_MIN_TO_VAL) { - NewTimeout = SK_RLMT_MIN_TO_VAL; - } - - if (!(pRPort->CheckingState & SK_RLMT_PCS_RX)) { - Para.Para32[0] = PortNumber; - pRPort->CheckingState |= SK_RLMT_PCS_RX; - - /* - * What shall we do if the port checked by this one receives - * our request frames? What's bad - our rx line or his tx line? - */ - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->DownRxTimer, - SK_RLMT_PORTDOWN_TIM_VAL, SKGE_RLMT, - SK_RLMT_PORTDOWN_RX_TIM, Para); - - for (i = 0; i < pRPort->PortsChecked; i++) { - if (pRPort->PortCheck[i].SuspectTx) { - continue; - } - pRPort->PortCheck[i].SuspectTx = SK_TRUE; - pRPort->PortsSuspect++; - if ((Para.pParaPtr = - SkRlmtBuildPacket(pAC, IoC, PortNumber, SK_PACKET_CHECK_TX, - &pAC->Addr.Port[PortNumber].CurrentMacAddress, - &pRPort->PortCheck[i].CheckAddr)) != NULL) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - } - } - else { /* PortDown -- or all partners suspect. */ - NewTimeout = SK_RLMT_DEF_TO_VAL; - } - pRPort->PortNoRx = SK_TRUE; - } - else { /* A non-BPDU packet was received. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SkRlmtCheckPort %d: %d (%d) receives in last time slot.\n", - PortNumber, - pRPort->PacketsPerTimeSlot - pRPort->BpduPacketsPerTimeSlot, - pRPort->PacketsPerTimeSlot)) - - SkRlmtPortReceives(pAC, IoC, PortNumber); - if (pAC->Rlmt.CheckSwitch) { - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - - NewTimeout = SK_RLMT_DEF_TO_VAL; - } - - return (NewTimeout); -} /* SkRlmtCheckPort */ - - -/****************************************************************************** - * - * SkRlmtSelectBcRx - select new active port, criteria 1 (CLP) - * - * Description: - * This routine selects the port that received a broadcast frame - * substantially later than all other ports. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectBcRx( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect) /* New active port */ -{ - SK_U64 BcTimeStamp; - SK_U32 i; - SK_BOOL PortFound; - - BcTimeStamp = 0; /* Not totally necessary, but feeling better. */ - PortFound = SK_FALSE; - - /* Select port with the latest TimeStamp. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("TimeStamp Port %d (Down: %d, NoRx: %d): %08x %08x.\n", - i, - pAC->Rlmt.Port[i].PortDown, pAC->Rlmt.Port[i].PortNoRx, - *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_HI32), - *((SK_U32*)(&pAC->Rlmt.Port[i].BcTimeStamp) + OFFS_LO32))) - - if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx) { - if (!PortFound || pAC->Rlmt.Port[i].BcTimeStamp > BcTimeStamp) { - BcTimeStamp = pAC->Rlmt.Port[i].BcTimeStamp; - *pSelect = i; - PortFound = SK_TRUE; - } - } - } - - if (PortFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d received the last broadcast.\n", *pSelect)) - - /* Look if another port's time stamp is similar. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (i == *pSelect) { - continue; - } - if (!pAC->Rlmt.Port[i].PortDown && !pAC->Rlmt.Port[i].PortNoRx && - (pAC->Rlmt.Port[i].BcTimeStamp > - BcTimeStamp - SK_RLMT_BC_DELTA || - pAC->Rlmt.Port[i].BcTimeStamp + - SK_RLMT_BC_DELTA > BcTimeStamp)) { - PortFound = SK_FALSE; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Port %d received a broadcast at a similar time.\n", i)) - break; - } - } - } - -#ifdef DEBUG - if (PortFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_BCRX found Port %d receiving the substantially " - "latest broadcast (%u).\n", - *pSelect, - BcTimeStamp - pAC->Rlmt.Port[1 - *pSelect].BcTimeStamp)) - } -#endif /* DEBUG */ - - return (PortFound); -} /* SkRlmtSelectBcRx */ - - -/****************************************************************************** - * - * SkRlmtSelectNotSuspect - select new active port, criteria 2 (CLP) - * - * Description: - * This routine selects a good port (it is PortUp && !SuspectRx). - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectNotSuspect( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect) /* New active port */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortUp && !SuspectRx. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (!pAC->Rlmt.Port[i].PortDown && - !(pAC->Rlmt.Port[i].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = i; - if (!pAC->Rlmt.Port[Active].PortDown && - !(pAC->Rlmt.Port[Active].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = Active; - } - if (!pAC->Rlmt.Port[PrefPort].PortDown && - !(pAC->Rlmt.Port[PrefPort].CheckingState & SK_RLMT_PCS_RX)) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_NOTSUSPECT found Port %d up and not check RX.\n", - *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectNotSuspect */ - - -/****************************************************************************** - * - * SkRlmtSelectUp - select new active port, criteria 3, 4 (CLP) - * - * Description: - * This routine selects a port that is up. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortUp. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - *pSelect = i; - if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { - *pSelect = Active; - } - if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_UP && - pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_UP found Port %d up.\n", *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectUp */ - - -/****************************************************************************** - * - * SkRlmtSelectGoingUp - select new active port, criteria 5, 6 (CLP) - * - * Description: - * This routine selects the port that is going up for the longest time. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectGoingUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U64 GuTimeStamp; - SK_U32 i; - SK_BOOL PortFound; - - GuTimeStamp = 0; - PortFound = SK_FALSE; - - /* Select port that is PortGoingUp for the longest time. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; - *pSelect = i; - PortFound = SK_TRUE; - break; - } - } - - if (!PortFound) { - return (SK_FALSE); - } - - for (i = *pSelect + 1; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_GOING_UP && - pAC->Rlmt.Port[i].GuTimeStamp < GuTimeStamp && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - GuTimeStamp = pAC->Rlmt.Port[i].GuTimeStamp; - *pSelect = i; - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_GOINGUP found Port %d going up.\n", *pSelect)) - return (SK_TRUE); -} /* SkRlmtSelectGoingUp */ - - -/****************************************************************************** - * - * SkRlmtSelectDown - select new active port, criteria 7, 8 (CLP) - * - * Description: - * This routine selects a port that is down. - * - * Context: - * runtime, pageable? - * - * Returns: - * SK_BOOL - */ -RLMT_STATIC SK_BOOL SkRlmtSelectDown( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Active, /* Active port */ -SK_U32 PrefPort, /* Preferred port */ -SK_U32 *pSelect, /* New active port */ -SK_BOOL AutoNegDone) /* Successfully auto-negotiated? */ -{ - SK_U32 i; - SK_BOOL PortFound; - - PortFound = SK_FALSE; - - /* Select first port that is PortDown. */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - if (pAC->Rlmt.Port[i].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[i].PAutoNegFail != AutoNegDone) { - *pSelect = i; - if (pAC->Rlmt.Port[Active].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[Active].PAutoNegFail != AutoNegDone) { - *pSelect = Active; - } - if (pAC->Rlmt.Port[PrefPort].PortState == SK_RLMT_PS_DOWN && - pAC->GIni.GP[PrefPort].PAutoNegFail != AutoNegDone) { - *pSelect = PrefPort; - } - PortFound = SK_TRUE; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SELECT_DOWN found Port %d down.\n", *pSelect)) - break; - } - } - return (PortFound); -} /* SkRlmtSelectDown */ - - -/****************************************************************************** - * - * SkRlmtCheckSwitch - select new active port and switch to it - * - * Description: - * This routine decides which port should be the active one and queues - * port switching if necessary. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtCheckSwitch( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 NetIdx) /* Net index */ -{ - SK_EVPARA Para; - SK_U32 Active; - SK_U32 PrefPort; - SK_U32 i; - SK_BOOL PortFound; - - Active = pAC->Rlmt.Net[NetIdx].ActivePort; /* Index of active port. */ - PrefPort = pAC->Rlmt.Net[NetIdx].PrefPort; /* Index of preferred port. */ - PortFound = SK_FALSE; - pAC->Rlmt.CheckSwitch = SK_FALSE; - -#if 0 /* RW 2001/10/18 - active port becomes always prefered one */ - if (pAC->Rlmt.Net[NetIdx].Preference == 0xFFFFFFFF) { /* Automatic */ - /* disable auto-fail back */ - PrefPort = Active; - } -#endif - - if (pAC->Rlmt.Net[NetIdx].LinksUp == 0) { - /* Last link went down - shut down the net. */ - pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_DOWN; - Para.Para32[0] = SK_RLMT_NET_DOWN_TEMP; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para); - - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); - return; - } /* pAC->Rlmt.LinksUp == 0 */ - else if (pAC->Rlmt.Net[NetIdx].LinksUp == 1 && - pAC->Rlmt.Net[NetIdx].RlmtState == SK_RLMT_RS_NET_DOWN) { - /* First link came up - get the net up. */ - pAC->Rlmt.Net[NetIdx].RlmtState = SK_RLMT_RS_NET_UP; - - /* - * If pAC->Rlmt.ActivePort != Para.Para32[0], - * the DRV switches to the port that came up. - */ - for (i = 0; i < pAC->Rlmt.Net[NetIdx].NumPorts; i++) { - if (!pAC->Rlmt.Net[NetIdx].Port[i]->LinkDown) { - if (!pAC->Rlmt.Net[NetIdx].Port[Active]->LinkDown) { - i = Active; - } - if (!pAC->Rlmt.Net[NetIdx].Port[PrefPort]->LinkDown) { - i = PrefPort; - } - PortFound = SK_TRUE; - break; - } - } - - if (PortFound) { - Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); - - pAC->Rlmt.Net[NetIdx].ActivePort = i; - Para.Para32[0] = pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber; - Para.Para32[1] = NetIdx; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_UP, Para); - - if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, - pAC->Rlmt.Net[NetIdx].Port[i]->PortNumber, - SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx]. - CurrentMacAddress, &SkRlmtMcAddr)) != NULL) { - /* - * Send announce packet to RLMT multicast address to force - * switches to learn the new location of the logical MAC address. - */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } - } - else { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E007, SKERR_RLMT_E007_MSG); - } - - return; - } /* LinksUp == 1 && RlmtState == SK_RLMT_RS_NET_DOWN */ - else { /* Cannot be reached in dual-net mode. */ - Para.Para32[0] = Active; - - /* - * Preselection: - * If RLMT Mode != CheckLinkState - * select port that received a broadcast frame substantially later - * than all other ports - * else select first port that is not SuspectRx - * else select first port that is PortUp - * else select port that is PortGoingUp for the longest time - * else select first port that is PortDown - * else stop. - * - * For the preselected port: - * If ActivePort is equal in quality, select ActivePort. - * - * If PrefPort is equal in quality, select PrefPort. - * - * If ActivePort != SelectedPort, - * If old ActivePort is LinkDown, - * SwitchHard - * else - * SwitchSoft - */ - /* check of ChgBcPrio flag added */ - if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && - (!pAC->Rlmt.Net[0].ChgBcPrio)) { - - if (!PortFound) { - PortFound = SkRlmtSelectBcRx( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - - if (!PortFound) { - PortFound = SkRlmtSelectNotSuspect( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - /* with changed priority for last broadcast received */ - if ((pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) && - (pAC->Rlmt.Net[0].ChgBcPrio)) { - if (!PortFound) { - PortFound = SkRlmtSelectNotSuspect( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - - if (!PortFound) { - PortFound = SkRlmtSelectBcRx( - pAC, IoC, Active, PrefPort, &Para.Para32[1]); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - if (!PortFound) { - PortFound = SkRlmtSelectUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - - if (!PortFound) { - PortFound = SkRlmtSelectGoingUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectGoingUp( - pAC, IoC, Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - - if (pAC->Rlmt.Net[0].RlmtMode != SK_RLMT_MODE_CLS) { - if (!PortFound) { - PortFound = SkRlmtSelectDown(pAC, IoC, - Active, PrefPort, &Para.Para32[1], AUTONEG_SUCCESS); - } - - if (!PortFound) { - PortFound = SkRlmtSelectDown(pAC, IoC, - Active, PrefPort, &Para.Para32[1], AUTONEG_FAILED); - } - } /* pAC->Rlmt.RlmtMode != SK_RLMT_MODE_CLS */ - - if (PortFound) { - - if (Para.Para32[1] != Active) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Active: %d, Para1: %d.\n", Active, Para.Para32[1])) - pAC->Rlmt.Net[NetIdx].ActivePort = Para.Para32[1]; - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[Para.Para32[0]]->PortNumber; - Para.Para32[1] = pAC->Rlmt.Net[NetIdx]. - Port[Para.Para32[1]]->PortNumber; - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[1], SK_LED_ACTIVE); - if (pAC->Rlmt.Port[Active].LinkDown) { - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_HARD, Para); - } - else { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); - SkEventQueue(pAC, SKGE_DRV, SK_DRV_SWITCH_SOFT, Para); - } - Para.Para32[1] = NetIdx; - Para.Para32[0] = - pAC->Rlmt.Net[NetIdx].Port[Para.Para32[0]]->PortNumber; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_DOWN, Para); - Para.Para32[0] = pAC->Rlmt.Net[NetIdx]. - Port[pAC->Rlmt.Net[NetIdx].ActivePort]->PortNumber; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_ACTIVE_UP, Para); - if ((pAC->Rlmt.Net[NetIdx].RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (Para.pParaPtr = SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], - SK_PACKET_ANNOUNCE, &pAC->Addr.Net[NetIdx].CurrentMacAddress, - &SkRlmtMcAddr)) != NULL) { - /* - * Send announce packet to RLMT multicast address to force - * switches to learn the new location of the logical - * MAC address. - */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para); - } /* (Para.pParaPtr = SkRlmtBuildPacket(...)) != NULL */ - } /* Para.Para32[1] != Active */ - } /* PortFound */ - else { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E004, SKERR_RLMT_E004_MSG); - } - } /* LinksUp > 1 || LinksUp == 1 && RlmtState != SK_RLMT_RS_NET_DOWN */ - return; -} /* SkRlmtCheckSwitch */ - - -/****************************************************************************** - * - * SkRlmtCheckSeg - Report if segmentation is detected - * - * Description: - * This routine checks if the ports see different root bridges and reports - * segmentation in such a case. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing. - */ -RLMT_STATIC void SkRlmtCheckSeg( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 NetIdx) /* Net number */ -{ - SK_EVPARA Para; - SK_RLMT_NET *pNet; - SK_U32 i, j; - SK_BOOL Equal; - - pNet = &pAC->Rlmt.Net[NetIdx]; - pNet->RootIdSet = SK_FALSE; - Equal = SK_TRUE; - - for (i = 0; i < pNet->NumPorts; i++) { - if (pNet->Port[i]->LinkDown || !pNet->Port[i]->RootIdSet) { - continue; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_DUMP, - ("Root ID %d: %02x %02x %02x %02x %02x %02x %02x %02x.\n", i, - pNet->Port[i]->Root.Id[0], pNet->Port[i]->Root.Id[1], - pNet->Port[i]->Root.Id[2], pNet->Port[i]->Root.Id[3], - pNet->Port[i]->Root.Id[4], pNet->Port[i]->Root.Id[5], - pNet->Port[i]->Root.Id[6], pNet->Port[i]->Root.Id[7])) - - if (!pNet->RootIdSet) { - pNet->Root = pNet->Port[i]->Root; - pNet->RootIdSet = SK_TRUE; - continue; - } - - for (j = 0; j < 8; j ++) { - Equal &= pNet->Port[i]->Root.Id[j] == pNet->Root.Id[j]; - if (!Equal) { - break; - } - } - - if (!Equal) { - SK_ERR_LOG(pAC, SK_ERRCL_COMM, SKERR_RLMT_E005, SKERR_RLMT_E005_MSG); - Para.Para32[0] = NetIdx; - Para.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SEGMENTATION, Para); - - pNet->CheckingState &= ~SK_RLMT_RCS_REPORT_SEG; - - /* 2000-03-06 RA: New. */ - Para.Para32[0] = NetIdx; - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pNet->SegTimer, SK_RLMT_SEG_TO_VAL, - SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - break; - } - } /* for (i = 0; i < pNet->NumPorts; i++) */ - - /* 2000-03-06 RA: Moved here. */ - /* Segmentation check not running anymore. */ - pNet->CheckingState &= ~SK_RLMT_RCS_SEG; - -} /* SkRlmtCheckSeg */ - - -/****************************************************************************** - * - * SkRlmtPortStart - initialize port variables and start port - * - * Description: - * This routine initializes a port's variables and issues a PORT_START - * to the HWAC module. This handles retries if the start fails or the - * link eventually goes down. - * - * Context: - * runtime, pageable? - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtPortStart( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 PortNumber) /* Port number */ -{ - SK_EVPARA Para; - - pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_LINK_DOWN; - pAC->Rlmt.Port[PortNumber].PortStarted = SK_TRUE; - pAC->Rlmt.Port[PortNumber].LinkDown = SK_TRUE; - pAC->Rlmt.Port[PortNumber].PortDown = SK_TRUE; - pAC->Rlmt.Port[PortNumber].CheckingState = 0; - pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; - Para.Para32[0] = PortNumber; - Para.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_START, Para); -} /* SkRlmtPortStart */ - - -/****************************************************************************** - * - * SkRlmtEvtPortStartTim - PORT_START_TIM - * - * Description: - * This routine handles PORT_START_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortStartTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Event EMPTY.\n")) - return; - } - - /* - * Used to start non-preferred ports if the preferred one - * does not come up. - * This timeout needs only be set when starting the first - * (preferred) port. - */ - if (pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { - /* PORT_START failed. */ - for (i = 0; i < pAC->Rlmt.Port[Para.Para32[0]].Net->NumPorts; i++) { - if (!pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortStarted) { - SkRlmtPortStart(pAC, IoC, - pAC->Rlmt.Port[Para.Para32[0]].Net->Port[i]->PortNumber); - } - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTSTART_TIMEOUT Event END.\n")) -} /* SkRlmtEvtPortStartTim */ - - -/****************************************************************************** - * - * SkRlmtEvtLinkUp - LINK_UP - * - * Description: - * This routine handles LLINK_UP events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtLinkUp( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ -{ - SK_U32 i; - SK_RLMT_PORT *pRPort; - SK_EVPARA Para2; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Port %d Event BEGIN.\n", Para.Para32[0])) - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (!pRPort->PortStarted) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E008, SKERR_RLMT_E008_MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event EMPTY.\n")) - return; - } - - if (!pRPort->LinkDown) { - /* RA;:;: Any better solution? */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event EMPTY.\n")) - return; - } - - SkTimerStop(pAC, IoC, &pRPort->UpTimer); - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - /* Do something if timer already fired? */ - - pRPort->LinkDown = SK_FALSE; - pRPort->PortState = SK_RLMT_PS_GOING_UP; - pRPort->GuTimeStamp = SkOsGetTime(pAC); - pRPort->BcTimeStamp = 0; - pRPort->Net->LinksUp++; - if (pRPort->Net->LinksUp == 1) { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_ACTIVE); - } - else { - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_STANDBY); - } - - for (i = 0; i < pRPort->Net->NumPorts; i++) { - if (!pRPort->Net->Port[i]->PortStarted) { - SkRlmtPortStart(pAC, IoC, pRPort->Net->Port[i]->PortNumber); - } - } - - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - - if (pRPort->Net->LinksUp >= 2) { - if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) { - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - } - } - - /* If the first link comes up, start the periodical RLMT timeout. */ - if (pRPort->Net->NumPorts > 1 && pRPort->Net->LinksUp == 1 && - (pRPort->Net->RlmtMode & SK_RLMT_CHECK_OTHERS) != 0) { - Para2.Para32[0] = pRPort->Net->NetNumber; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->Net->LocTimer, - pRPort->Net->TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, Para2); - } - - Para2 = Para; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->UpTimer, SK_RLMT_PORTUP_TIM_VAL, - SKGE_RLMT, SK_RLMT_PORTUP_TIM, Para2); - - /* Later: if (pAC->Rlmt.RlmtMode & SK_RLMT_CHECK_LOC_LINK) && */ - if ((pRPort->Net->RlmtMode & SK_RLMT_TRANSPARENT) == 0 && - (pRPort->Net->RlmtMode & SK_RLMT_CHECK_LINK) != 0 && - (Para2.pParaPtr = - SkRlmtBuildPacket(pAC, IoC, Para.Para32[0], SK_PACKET_ANNOUNCE, - &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress, &SkRlmtMcAddr) - ) != NULL) { - /* Send "new" packet to RLMT multicast address. */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - } - - if (pRPort->Net->RlmtMode & SK_RLMT_CHECK_SEG) { - if ((Para2.pParaPtr = - SkRlmtBuildSpanningTreePacket(pAC, IoC, Para.Para32[0])) != NULL) { - pAC->Rlmt.Port[Para.Para32[0]].RootIdSet = SK_FALSE; - pRPort->Net->CheckingState |= - SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; - - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - - Para.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pRPort->Net->SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_UP Event END.\n")) -} /* SkRlmtEvtLinkUp */ - - -/****************************************************************************** - * - * SkRlmtEvtPortUpTim - PORT_UP_TIM - * - * Description: - * This routine handles PORT_UP_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortUpTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Event EMPTY.\n")) - return; - } - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (pRPort->LinkDown || (pRPort->PortState == SK_RLMT_PS_UP)) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Port %d Event EMPTY.\n", Para.Para32[0])) - return; - } - - pRPort->PortDown = SK_FALSE; - pRPort->PortState = SK_RLMT_PS_UP; - pRPort->Net->PortsUp++; - if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { - if (pAC->Rlmt.NumNets <= 1) { - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_UP, Para); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTUP_TIM Event END.\n")) -} /* SkRlmtEvtPortUpTim */ - - -/****************************************************************************** - * - * SkRlmtEvtPortDownTim - PORT_DOWN_* - * - * Description: - * This routine handles PORT_DOWN_* events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortDownX( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Event code */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Port %d Event (%d) BEGIN.\n", - Para.Para32[0], Event)) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event EMPTY.\n")) - return; - } - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - if (!pRPort->PortStarted || (Event == SK_RLMT_PORTDOWN_TX_TIM && - !(pRPort->CheckingState & SK_RLMT_PCS_TX))) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event (%d) EMPTY.\n", Event)) - return; - } - - /* Stop port's timers. */ - SkTimerStop(pAC, IoC, &pRPort->UpTimer); - SkTimerStop(pAC, IoC, &pRPort->DownRxTimer); - SkTimerStop(pAC, IoC, &pRPort->DownTxTimer); - - if (pRPort->PortState != SK_RLMT_PS_LINK_DOWN) { - pRPort->PortState = SK_RLMT_PS_DOWN; - } - - if (!pRPort->PortDown) { - pRPort->Net->PortsUp--; - pRPort->PortDown = SK_TRUE; - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_PORT_DOWN, Para); - } - - pRPort->PacketsPerTimeSlot = 0; - /* pRPort->DataPacketsPerTimeSlot = 0; */ - pRPort->BpduPacketsPerTimeSlot = 0; - pRPort->BcTimeStamp = 0; - - /* - * RA;:;: To be checked: - * - actions at RLMT_STOP: We should not switch anymore. - */ - if (pRPort->Net->RlmtState != SK_RLMT_RS_INIT) { - if (Para.Para32[0] == - pRPort->Net->Port[pRPort->Net->ActivePort]->PortNumber) { - /* Active Port went down. */ - SkRlmtCheckSwitch(pAC, IoC, pRPort->Net->NetNumber); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORTDOWN* Event (%d) END.\n", Event)) -} /* SkRlmtEvtPortDownX */ - - -/****************************************************************************** - * - * SkRlmtEvtLinkDown - LINK_DOWN - * - * Description: - * This routine handles LINK_DOWN events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtLinkDown( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 Undefined */ -{ - SK_RLMT_PORT *pRPort; - - pRPort = &pAC->Rlmt.Port[Para.Para32[0]]; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_DOWN Port %d Event BEGIN.\n", Para.Para32[0])) - - if (!pAC->Rlmt.Port[Para.Para32[0]].LinkDown) { - pRPort->Net->LinksUp--; - pRPort->LinkDown = SK_TRUE; - pRPort->PortState = SK_RLMT_PS_LINK_DOWN; - SK_HWAC_LINK_LED(pAC, IoC, Para.Para32[0], SK_LED_OFF); - - if ((pRPort->Net->RlmtMode & SK_RLMT_CHECK_LOC_LINK) != 0) { - /* Build the check chain. */ - SkRlmtBuildCheckChain(pAC, pRPort->Net->NetNumber); - } - - /* Ensure that port is marked down. */ - Para.Para32[1] = -1; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PORTDOWN, Para); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_LINK_DOWN Event END.\n")) -} /* SkRlmtEvtLinkDown */ - - -/****************************************************************************** - * - * SkRlmtEvtPortAddr - PORT_ADDR - * - * Description: - * This routine handles PORT_ADDR events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPortAddr( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortNumber; SK_U32 -1 */ -{ - SK_U32 i, j; - SK_RLMT_PORT *pRPort; - SK_MAC_ADDR *pOldMacAddr; - SK_MAC_ADDR *pNewMacAddr; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Event EMPTY.\n")) - return; - } - - /* Port's physical MAC address changed. */ - pOldMacAddr = &pAC->Addr.Port[Para.Para32[0]].PreviousMacAddress; - pNewMacAddr = &pAC->Addr.Port[Para.Para32[0]].CurrentMacAddress; - - /* - * NOTE: This is not scalable for solutions where ports are - * checked remotely. There, we need to send an RLMT - * address change packet - and how do we ensure delivery? - */ - for (i = 0; i < (SK_U32)pAC->GIni.GIMacsFound; i++) { - pRPort = &pAC->Rlmt.Port[i]; - for (j = 0; j < pRPort->PortsChecked; j++) { - if (SK_ADDR_EQUAL( - pRPort->PortCheck[j].CheckAddr.a, pOldMacAddr->a)) { - pRPort->PortCheck[j].CheckAddr = *pNewMacAddr; - } - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PORT_ADDR Event END.\n")) -} /* SkRlmtEvtPortAddr */ - - -/****************************************************************************** - * - * SkRlmtEvtStart - START - * - * Description: - * This routine handles START events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStart( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_EVPARA Para2; - SK_U32 PortIdx; - SK_U32 PortNumber; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Net %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState != SK_RLMT_RS_INIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.NetsStarted >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("All nets should have been started.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].PrefPort >= - pAC->Rlmt.Net[Para.Para32[0]].NumPorts) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E009, SKERR_RLMT_E009_MSG); - - /* Change PrefPort to internal default. */ - Para2.Para32[0] = 0xFFFFFFFF; - Para2.Para32[1] = Para.Para32[0]; - (void)SkRlmtEvent(pAC, IoC, SK_RLMT_PREFPORT_CHANGE, Para2); - } - - PortIdx = pAC->Rlmt.Net[Para.Para32[0]].PrefPort; - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[PortIdx]->PortNumber; - - pAC->Rlmt.Net[Para.Para32[0]].LinksUp = 0; - pAC->Rlmt.Net[Para.Para32[0]].PortsUp = 0; - pAC->Rlmt.Net[Para.Para32[0]].CheckingState = 0; - pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_NET_DOWN; - - /* Start preferred port. */ - SkRlmtPortStart(pAC, IoC, PortNumber); - - /* Start Timer (for first port only). */ - Para2.Para32[0] = PortNumber; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer, - SK_RLMT_PORTSTART_TIM_VAL, SKGE_RLMT, SK_RLMT_PORTSTART_TIM, Para2); - - pAC->Rlmt.NetsStarted++; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_START Event END.\n")) -} /* SkRlmtEvtStart */ - - -/****************************************************************************** - * - * SkRlmtEvtStop - STOP - * - * Description: - * This routine handles STOP events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStop( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_EVPARA Para2; - SK_U32 PortNumber; - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Net %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.Net[Para.Para32[0]].RlmtState == SK_RLMT_RS_INIT) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - if (pAC->Rlmt.NetsStarted == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("All nets are stopped.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event EMPTY.\n")) - return; - } - - /* Stop RLMT timers. */ - SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer); - - /* Stop net. */ - pAC->Rlmt.Net[Para.Para32[0]].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[Para.Para32[0]].RootIdSet = SK_FALSE; - Para2.Para32[0] = SK_RLMT_NET_DOWN_FINAL; - Para2.Para32[1] = Para.Para32[0]; /* Net# */ - SkEventQueue(pAC, SKGE_DRV, SK_DRV_NET_DOWN, Para2); - - /* Stop ports. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; - if (pAC->Rlmt.Port[PortNumber].PortState != SK_RLMT_PS_INIT) { - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].UpTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownRxTimer); - SkTimerStop(pAC, IoC, &pAC->Rlmt.Port[PortNumber].DownTxTimer); - - pAC->Rlmt.Port[PortNumber].PortState = SK_RLMT_PS_INIT; - pAC->Rlmt.Port[PortNumber].RootIdSet = SK_FALSE; - pAC->Rlmt.Port[PortNumber].PortStarted = SK_FALSE; - Para2.Para32[0] = PortNumber; - Para2.Para32[1] = (SK_U32)-1; - SkEventQueue(pAC, SKGE_HWAC, SK_HWEV_PORT_STOP, Para2); - } - } - - pAC->Rlmt.NetsStarted--; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STOP Event END.\n")) -} /* SkRlmtEvtStop */ - - -/****************************************************************************** - * - * SkRlmtEvtTim - TIM - * - * Description: - * This routine handles TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_RLMT_PORT *pRPort; - SK_U32 Timeout; - SK_U32 NewTimeout; - SK_U32 PortNumber; - SK_U32 i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event EMPTY.\n")) - return; - } - - if ((pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_OTHERS) == 0 || - pAC->Rlmt.Net[Para.Para32[0]].LinksUp == 0) { - /* Mode changed or all links down: No more link checking. */ - return; - } - -#if 0 - pAC->Rlmt.SwitchCheckCounter--; - if (pAC->Rlmt.SwitchCheckCounter == 0) { - pAC->Rlmt.SwitchCheckCounter; - } -#endif /* 0 */ - - NewTimeout = SK_RLMT_DEF_TO_VAL; - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - PortNumber = pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber; - pRPort = &pAC->Rlmt.Port[PortNumber]; - if (!pRPort->LinkDown) { - Timeout = SkRlmtCheckPort(pAC, IoC, PortNumber); - if (Timeout < NewTimeout) { - NewTimeout = Timeout; - } - - /* - * These counters should be set to 0 for all ports before the - * first frame is sent in the next loop. - */ - pRPort->PacketsPerTimeSlot = 0; - /* pRPort->DataPacketsPerTimeSlot = 0; */ - pRPort->BpduPacketsPerTimeSlot = 0; - } - } - pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue = NewTimeout; - - if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1) { - /* - * If checking remote ports, also send packets if - * (LinksUp == 1) && - * this port checks at least one (remote) port. - */ - - /* - * Must be new loop, as SkRlmtCheckPort can request to - * check segmentation when e.g. checking the last port. - */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - if (!pAC->Rlmt.Net[Para.Para32[0]].Port[i]->LinkDown) { - SkRlmtSend(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber); - } - } - } - - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].LocTimer, - pAC->Rlmt.Net[Para.Para32[0]].TimeoutValue, SKGE_RLMT, SK_RLMT_TIM, - Para); - - if (pAC->Rlmt.Net[Para.Para32[0]].LinksUp > 1 && - (pAC->Rlmt.Net[Para.Para32[0]].RlmtMode & SK_RLMT_CHECK_SEG) && - (pAC->Rlmt.Net[Para.Para32[0]].CheckingState & SK_RLMT_RCS_START_SEG)) { - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[0]].SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para); - pAC->Rlmt.Net[Para.Para32[0]].CheckingState &= ~SK_RLMT_RCS_START_SEG; - pAC->Rlmt.Net[Para.Para32[0]].CheckingState |= - SK_RLMT_RCS_SEG | SK_RLMT_RCS_REPORT_SEG; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_TIM Event END.\n")) -} /* SkRlmtEvtTim */ - - -/****************************************************************************** - * - * SkRlmtEvtSegTim - SEG_TIM - * - * Description: - * This routine handles SEG_TIM events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtSegTim( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ -#ifdef xDEBUG - int j; -#endif /* DEBUG */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event EMPTY.\n")) - return; - } - -#ifdef xDEBUG - for (j = 0; j < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; j++) { - SK_ADDR_PORT *pAPort; - SK_U32 k; - SK_U16 *InAddr; - SK_U8 InAddr8[6]; - - InAddr = (SK_U16 *)&InAddr8[0]; - pAPort = pAC->Rlmt.Net[Para.Para32[0]].Port[j]->AddrPort; - for (k = 0; k < pAPort->NextExactMatchRlmt; k++) { - /* Get exact match address k from port j. */ - XM_INADDR(IoC, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, - XM_EXM(k), InAddr); - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("MC address %d on Port %u: %02x %02x %02x %02x %02x %02x -- %02x %02x %02x %02x %02x %02x.\n", - k, pAC->Rlmt.Net[Para.Para32[0]].Port[j]->PortNumber, - InAddr8[0], InAddr8[1], InAddr8[2], - InAddr8[3], InAddr8[4], InAddr8[5], - pAPort->Exact[k].a[0], pAPort->Exact[k].a[1], - pAPort->Exact[k].a[2], pAPort->Exact[k].a[3], - pAPort->Exact[k].a[4], pAPort->Exact[k].a[5])) - } - } -#endif /* xDEBUG */ - - SkRlmtCheckSeg(pAC, IoC, Para.Para32[0]); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SEG_TIM Event END.\n")) -} /* SkRlmtEvtSegTim */ - - -/****************************************************************************** - * - * SkRlmtEvtPacketRx - PACKET_RECEIVED - * - * Description: - * This routine handles PACKET_RECEIVED events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPacketRx( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_MBUF *pMb */ -{ - SK_MBUF *pMb; - SK_MBUF *pNextMb; - SK_U32 NetNumber; - - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PACKET_RECEIVED Event BEGIN.\n")) - - /* Should we ignore frames during port switching? */ - -#ifdef DEBUG - pMb = Para.pParaPtr; - if (pMb == NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, ("No mbuf.\n")) - } - else if (pMb->pNext != NULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("More than one mbuf or pMb->pNext not set.\n")) - } -#endif /* DEBUG */ - - for (pMb = Para.pParaPtr; pMb != NULL; pMb = pNextMb) { - pNextMb = pMb->pNext; - pMb->pNext = NULL; - - NetNumber = pAC->Rlmt.Port[pMb->PortIdx].Net->NetNumber; - if (pAC->Rlmt.Net[NetNumber].RlmtState == SK_RLMT_RS_INIT) { - SkDrvFreeRlmtMbuf(pAC, IoC, pMb); - } - else { - SkRlmtPacketReceive(pAC, IoC, pMb); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PACKET_RECEIVED Event END.\n")) -} /* SkRlmtEvtPacketRx */ - - -/****************************************************************************** - * - * SkRlmtEvtStatsClear - STATS_CLEAR - * - * Description: - * This routine handles STATS_CLEAR events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStatsClear( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_U32 i; - SK_RLMT_PORT *pRPort; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event EMPTY.\n")) - return; - } - - /* Clear statistics for logical and physical ports. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[0]].NumPorts; i++) { - pRPort = - &pAC->Rlmt.Port[pAC->Rlmt.Net[Para.Para32[0]].Port[i]->PortNumber]; - pRPort->TxHelloCts = 0; - pRPort->RxHelloCts = 0; - pRPort->TxSpHelloReqCts = 0; - pRPort->RxSpHelloCts = 0; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_CLEAR Event END.\n")) -} /* SkRlmtEvtStatsClear */ - - -/****************************************************************************** - * - * SkRlmtEvtStatsUpdate - STATS_UPDATE - * - * Description: - * This routine handles STATS_UPDATE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtStatsUpdate( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NetNumber; SK_U32 -1 */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event EMPTY.\n")) - return; - } - - /* Update statistics - currently always up-to-date. */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_STATS_UPDATE Event END.\n")) -} /* SkRlmtEvtStatsUpdate */ - - -/****************************************************************************** - * - * SkRlmtEvtPrefportChange - PREFPORT_CHANGE - * - * Description: - * This routine handles PREFPORT_CHANGE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtPrefportChange( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 PortIndex; SK_U32 NetNumber */ -{ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE to Port %d Event BEGIN.\n", Para.Para32[0])) - - if (Para.Para32[1] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[1])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) - return; - } - - /* 0xFFFFFFFF == auto-mode. */ - if (Para.Para32[0] == 0xFFFFFFFF) { - pAC->Rlmt.Net[Para.Para32[1]].PrefPort = SK_RLMT_DEF_PREF_PORT; - } - else { - if (Para.Para32[0] >= pAC->Rlmt.Net[Para.Para32[1]].NumPorts) { - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E010, SKERR_RLMT_E010_MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event EMPTY.\n")) - return; - } - - pAC->Rlmt.Net[Para.Para32[1]].PrefPort = Para.Para32[0]; - } - - pAC->Rlmt.Net[Para.Para32[1]].Preference = Para.Para32[0]; - - if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { - SkRlmtCheckSwitch(pAC, IoC, Para.Para32[1]); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_PREFPORT_CHANGE Event END.\n")) -} /* SkRlmtEvtPrefportChange */ - - -/****************************************************************************** - * - * SkRlmtEvtSetNets - SET_NETS - * - * Description: - * This routine handles SET_NETS events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtSetNets( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NumNets; SK_U32 -1 */ -{ - int i; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event BEGIN.\n")) - - if (Para.Para32[1] != (SK_U32)-1) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad Parameter.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == 0 || Para.Para32[0] > SK_MAX_NETS || - Para.Para32[0] > (SK_U32)pAC->GIni.GIMacsFound) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad number of nets: %d.\n", Para.Para32[0])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == pAC->Rlmt.NumNets) { /* No change. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - /* Entering and leaving dual mode only allowed while nets are stopped. */ - if (pAC->Rlmt.NetsStarted > 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Changing dual mode only allowed while all nets are stopped.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - if (Para.Para32[0] == 1) { - if (pAC->Rlmt.NumNets > 1) { - /* Clear logical MAC addr from second net's active port. */ - (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. - Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_CLEAR_LOGICAL); - pAC->Rlmt.Net[1].NumPorts = 0; - } - - pAC->Rlmt.NumNets = Para.Para32[0]; - for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - pAC->Rlmt.Net[i].NetNumber = i; - } - - pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[0]; - pAC->Rlmt.Net[0].NumPorts = pAC->GIni.GIMacsFound; - - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("RLMT: Changed to one net with two ports.\n")) - } - else if (Para.Para32[0] == 2) { - pAC->Rlmt.Port[1].Net= &pAC->Rlmt.Net[1]; - pAC->Rlmt.Net[1].NumPorts = pAC->GIni.GIMacsFound - 1; - pAC->Rlmt.Net[0].NumPorts = - pAC->GIni.GIMacsFound - pAC->Rlmt.Net[1].NumPorts; - - pAC->Rlmt.NumNets = Para.Para32[0]; - for (i = 0; (SK_U32)i < pAC->Rlmt.NumNets; i++) { - pAC->Rlmt.Net[i].RlmtState = SK_RLMT_RS_INIT; - pAC->Rlmt.Net[i].RootIdSet = SK_FALSE; - pAC->Rlmt.Net[i].Preference = 0xFFFFFFFF; /* "Automatic" */ - pAC->Rlmt.Net[i].PrefPort = SK_RLMT_DEF_PREF_PORT; - /* Just assuming. */ - pAC->Rlmt.Net[i].ActivePort = pAC->Rlmt.Net[i].PrefPort; - pAC->Rlmt.Net[i].RlmtMode = SK_RLMT_DEF_MODE; - pAC->Rlmt.Net[i].TimeoutValue = SK_RLMT_DEF_TO_VAL; - - pAC->Rlmt.Net[i].NetNumber = i; - } - - /* Set logical MAC addr on second net's active port. */ - (void)SkAddrOverride(pAC, IoC, pAC->Rlmt.Net[1].Port[pAC->Addr. - Net[1].ActivePort]->PortNumber, NULL, SK_ADDR_SET_LOGICAL); - - SkEventQueue(pAC, SKGE_PNMI, SK_PNMI_EVT_RLMT_SET_NETS, Para); - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("RLMT: Changed to two nets with one port each.\n")) - } - else { - /* Not implemented for more than two nets. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SetNets not implemented for more than two nets.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event EMPTY.\n")) - return; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_SET_NETS Event END.\n")) -} /* SkRlmtSetNets */ - - -/****************************************************************************** - * - * SkRlmtEvtModeChange - MODE_CHANGE - * - * Description: - * This routine handles MODE_CHANGE events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * Nothing - */ -RLMT_STATIC void SkRlmtEvtModeChange( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_EVPARA Para) /* SK_U32 NewMode; SK_U32 NetNumber */ -{ - SK_EVPARA Para2; - SK_U32 i; - SK_U32 PrevRlmtMode; - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event BEGIN.\n")) - - if (Para.Para32[1] >= pAC->Rlmt.NumNets) { - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Bad NetNumber %d.\n", Para.Para32[1])) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) - return; - } - - Para.Para32[0] |= SK_RLMT_CHECK_LINK; - - if ((pAC->Rlmt.Net[Para.Para32[1]].NumPorts == 1) && - Para.Para32[0] != SK_RLMT_MODE_CLS) { - pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = SK_RLMT_MODE_CLS; - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Forced RLMT mode to CLS on single port net.\n")) - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event EMPTY.\n")) - return; - } - - /* Update RLMT mode. */ - PrevRlmtMode = pAC->Rlmt.Net[Para.Para32[1]].RlmtMode; - pAC->Rlmt.Net[Para.Para32[1]].RlmtMode = Para.Para32[0]; - - if ((PrevRlmtMode & SK_RLMT_CHECK_LOC_LINK) != - (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_LOC_LINK)) { - /* SK_RLMT_CHECK_LOC_LINK bit changed. */ - if ((PrevRlmtMode & SK_RLMT_CHECK_OTHERS) == 0 && - pAC->Rlmt.Net[Para.Para32[1]].NumPorts > 1 && - pAC->Rlmt.Net[Para.Para32[1]].PortsUp >= 1) { - /* 20001207 RA: Was "PortsUp == 1". */ - Para2.Para32[0] = Para.Para32[1]; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].LocTimer, - pAC->Rlmt.Net[Para.Para32[1]].TimeoutValue, - SKGE_RLMT, SK_RLMT_TIM, Para2); - } - } - - if ((PrevRlmtMode & SK_RLMT_CHECK_SEG) != - (pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG)) { - /* SK_RLMT_CHECK_SEG bit changed. */ - for (i = 0; i < pAC->Rlmt.Net[Para.Para32[1]].NumPorts; i++) { - (void)SkAddrMcClear(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - SK_ADDR_PERMANENT | SK_MC_SW_ONLY); - - /* Add RLMT MC address. */ - (void)SkAddrMcAdd(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - &SkRlmtMcAddr, SK_ADDR_PERMANENT); - - if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & - SK_RLMT_CHECK_SEG) != 0) { - /* Add BPDU MC address. */ - (void)SkAddrMcAdd(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber, - &BridgeMcAddr, SK_ADDR_PERMANENT); - - if (pAC->Rlmt.Net[Para.Para32[1]].RlmtState != SK_RLMT_RS_INIT) { - if (!pAC->Rlmt.Net[Para.Para32[1]].Port[i]->LinkDown && - (Para2.pParaPtr = SkRlmtBuildSpanningTreePacket( - pAC, IoC, i)) != NULL) { - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->RootIdSet = - SK_FALSE; - SkEventQueue(pAC, SKGE_DRV, SK_DRV_RLMT_SEND, Para2); - } - } - } - (void)SkAddrMcUpdate(pAC, IoC, - pAC->Rlmt.Net[Para.Para32[1]].Port[i]->PortNumber); - } /* for ... */ - - if ((pAC->Rlmt.Net[Para.Para32[1]].RlmtMode & SK_RLMT_CHECK_SEG) != 0) { - Para2.Para32[0] = Para.Para32[1]; - Para2.Para32[1] = (SK_U32)-1; - SkTimerStart(pAC, IoC, &pAC->Rlmt.Net[Para.Para32[1]].SegTimer, - SK_RLMT_SEG_TO_VAL, SKGE_RLMT, SK_RLMT_SEG_TIM, Para2); - } - } /* SK_RLMT_CHECK_SEG bit changed. */ - - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("SK_RLMT_MODE_CHANGE Event END.\n")) -} /* SkRlmtEvtModeChange */ - - -/****************************************************************************** - * - * SkRlmtEvent - a PORT- or an RLMT-specific event happened - * - * Description: - * This routine calls subroutines to handle PORT- and RLMT-specific events. - * - * Context: - * runtime, pageable? - * may be called after SK_INIT_IO - * - * Returns: - * 0 - */ -int SkRlmtEvent( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -SK_U32 Event, /* Event code */ -SK_EVPARA Para) /* Event-specific parameter */ -{ - switch (Event) { - - /* ----- PORT events ----- */ - - case SK_RLMT_PORTSTART_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortStartTim(pAC, IoC, Para); - break; - case SK_RLMT_LINK_UP: /* From SIRQ. */ - SkRlmtEvtLinkUp(pAC, IoC, Para); - break; - case SK_RLMT_PORTUP_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortUpTim(pAC, IoC, Para); - break; - case SK_RLMT_PORTDOWN: /* From RLMT. */ - case SK_RLMT_PORTDOWN_RX_TIM: /* From RLMT via TIME. */ - case SK_RLMT_PORTDOWN_TX_TIM: /* From RLMT via TIME. */ - SkRlmtEvtPortDownX(pAC, IoC, Event, Para); - break; - case SK_RLMT_LINK_DOWN: /* From SIRQ. */ - SkRlmtEvtLinkDown(pAC, IoC, Para); - break; - case SK_RLMT_PORT_ADDR: /* From ADDR. */ - SkRlmtEvtPortAddr(pAC, IoC, Para); - break; - - /* ----- RLMT events ----- */ - - case SK_RLMT_START: /* From DRV. */ - SkRlmtEvtStart(pAC, IoC, Para); - break; - case SK_RLMT_STOP: /* From DRV. */ - SkRlmtEvtStop(pAC, IoC, Para); - break; - case SK_RLMT_TIM: /* From RLMT via TIME. */ - SkRlmtEvtTim(pAC, IoC, Para); - break; - case SK_RLMT_SEG_TIM: - SkRlmtEvtSegTim(pAC, IoC, Para); - break; - case SK_RLMT_PACKET_RECEIVED: /* From DRV. */ - SkRlmtEvtPacketRx(pAC, IoC, Para); - break; - case SK_RLMT_STATS_CLEAR: /* From PNMI. */ - SkRlmtEvtStatsClear(pAC, IoC, Para); - break; - case SK_RLMT_STATS_UPDATE: /* From PNMI. */ - SkRlmtEvtStatsUpdate(pAC, IoC, Para); - break; - case SK_RLMT_PREFPORT_CHANGE: /* From PNMI. */ - SkRlmtEvtPrefportChange(pAC, IoC, Para); - break; - case SK_RLMT_MODE_CHANGE: /* From PNMI. */ - SkRlmtEvtModeChange(pAC, IoC, Para); - break; - case SK_RLMT_SET_NETS: /* From DRV. */ - SkRlmtEvtSetNets(pAC, IoC, Para); - break; - - /* ----- Unknown events ----- */ - - default: /* Create error log entry. */ - SK_DBG_MSG(pAC, SK_DBGMOD_RLMT, SK_DBGCAT_CTRL, - ("Unknown RLMT Event %d.\n", Event)) - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_RLMT_E003, SKERR_RLMT_E003_MSG); - break; - } /* switch() */ - - return (0); -} /* SkRlmtEvent */ - -#ifdef __cplusplus -} -#endif /* __cplusplus */ diff --git a/drivers/net/sk98lin/sktimer.c b/drivers/net/sk98lin/sktimer.c deleted file mode 100644 index 4e462955ecd8..000000000000 --- a/drivers/net/sk98lin/sktimer.c +++ /dev/null @@ -1,250 +0,0 @@ -/****************************************************************************** - * - * Name: sktimer.c - * Project: Gigabit Ethernet Adapters, Event Scheduler Module - * Version: $Revision: 1.14 $ - * Date: $Date: 2003/09/16 13:46:51 $ - * Purpose: High level timer functions. - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect GmbH. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - - -/* - * Event queue and dispatcher - */ -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: sktimer.c,v 1.14 2003/09/16 13:46:51 rschmidt Exp $ (C) Marvell."; -#endif - -#include "h/skdrv1st.h" /* Driver Specific Definitions */ -#include "h/skdrv2nd.h" /* Adapter Control- and Driver specific Def. */ - -#ifdef __C2MAN__ -/* - Event queue management. - - General Description: - - */ -intro() -{} -#endif - - -/* Forward declaration */ -static void timer_done(SK_AC *pAC,SK_IOC Ioc,int Restart); - - -/* - * Inits the software timer - * - * needs to be called during Init level 1. - */ -void SkTimerInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -int Level) /* Init Level */ -{ - switch (Level) { - case SK_INIT_DATA: - pAC->Tim.StQueue = NULL; - break; - case SK_INIT_IO: - SkHwtInit(pAC, Ioc); - SkTimerDone(pAC, Ioc); - break; - default: - break; - } -} - -/* - * Stops a high level timer - * - If a timer is not in the queue the function returns normally, too. - */ -void SkTimerStop( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_TIMER *pTimer) /* Timer Pointer to be started */ -{ - SK_TIMER **ppTimPrev; - SK_TIMER *pTm; - - /* - * remove timer from queue - */ - pTimer->TmActive = SK_FALSE; - - if (pAC->Tim.StQueue == pTimer && !pTimer->TmNext) { - SkHwtStop(pAC, Ioc); - } - - for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); - ppTimPrev = &pTm->TmNext ) { - - if (pTm == pTimer) { - /* - * Timer found in queue - * - dequeue it and - * - correct delta of the next timer - */ - *ppTimPrev = pTm->TmNext; - - if (pTm->TmNext) { - /* correct delta of next timer in queue */ - pTm->TmNext->TmDelta += pTm->TmDelta; - } - return; - } - } -} - -/* - * Start a high level software timer - */ -void SkTimerStart( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -SK_TIMER *pTimer, /* Timer Pointer to be started */ -SK_U32 Time, /* Time value */ -SK_U32 Class, /* Event Class for this timer */ -SK_U32 Event, /* Event Value for this timer */ -SK_EVPARA Para) /* Event Parameter for this timer */ -{ - SK_TIMER **ppTimPrev; - SK_TIMER *pTm; - SK_U32 Delta; - - Time /= 16; /* input is uS, clock ticks are 16uS */ - - if (!Time) - Time = 1; - - SkTimerStop(pAC, Ioc, pTimer); - - pTimer->TmClass = Class; - pTimer->TmEvent = Event; - pTimer->TmPara = Para; - pTimer->TmActive = SK_TRUE; - - if (!pAC->Tim.StQueue) { - /* First Timer to be started */ - pAC->Tim.StQueue = pTimer; - pTimer->TmNext = NULL; - pTimer->TmDelta = Time; - - SkHwtStart(pAC, Ioc, Time); - - return; - } - - /* - * timer correction - */ - timer_done(pAC, Ioc, 0); - - /* - * find position in queue - */ - Delta = 0; - for (ppTimPrev = &pAC->Tim.StQueue; (pTm = *ppTimPrev); - ppTimPrev = &pTm->TmNext ) { - - if (Delta + pTm->TmDelta > Time) { - /* Position found */ - /* Here the timer needs to be inserted. */ - break; - } - Delta += pTm->TmDelta; - } - - /* insert in queue */ - *ppTimPrev = pTimer; - pTimer->TmNext = pTm; - pTimer->TmDelta = Time - Delta; - - if (pTm) { - /* There is a next timer - * -> correct its Delta value. - */ - pTm->TmDelta -= pTimer->TmDelta; - } - - /* restart with first */ - SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); -} - - -void SkTimerDone( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc) /* IoContext */ -{ - timer_done(pAC, Ioc, 1); -} - - -static void timer_done( -SK_AC *pAC, /* Adapters context */ -SK_IOC Ioc, /* IoContext */ -int Restart) /* Do we need to restart the Hardware timer ? */ -{ - SK_U32 Delta; - SK_TIMER *pTm; - SK_TIMER *pTComp; /* Timer completed now now */ - SK_TIMER **ppLast; /* Next field of Last timer to be deq */ - int Done = 0; - - Delta = SkHwtRead(pAC, Ioc); - - ppLast = &pAC->Tim.StQueue; - pTm = pAC->Tim.StQueue; - while (pTm && !Done) { - if (Delta >= pTm->TmDelta) { - /* Timer ran out */ - pTm->TmActive = SK_FALSE; - Delta -= pTm->TmDelta; - ppLast = &pTm->TmNext; - pTm = pTm->TmNext; - } - else { - /* We found the first timer that did not run out */ - pTm->TmDelta -= Delta; - Delta = 0; - Done = 1; - } - } - *ppLast = NULL; - /* - * pTm points to the first Timer that did not run out. - * StQueue points to the first Timer that run out. - */ - - for ( pTComp = pAC->Tim.StQueue; pTComp; pTComp = pTComp->TmNext) { - SkEventQueue(pAC,pTComp->TmClass, pTComp->TmEvent, pTComp->TmPara); - } - - /* Set head of timer queue to the first timer that did not run out */ - pAC->Tim.StQueue = pTm; - - if (Restart && pAC->Tim.StQueue) { - /* Restart HW timer */ - SkHwtStart(pAC, Ioc, pAC->Tim.StQueue->TmDelta); - } -} - -/* End of file */ diff --git a/drivers/net/sk98lin/skvpd.c b/drivers/net/sk98lin/skvpd.c deleted file mode 100644 index 1e662aaebf84..000000000000 --- a/drivers/net/sk98lin/skvpd.c +++ /dev/null @@ -1,1091 +0,0 @@ -/****************************************************************************** - * - * Name: skvpd.c - * Project: GEnesis, PCI Gigabit Ethernet Adapter - * Version: $Revision: 1.37 $ - * Date: $Date: 2003/01/13 10:42:45 $ - * Purpose: Shared software to read and write VPD data - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2003 SysKonnect GmbH. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -/* - Please refer skvpd.txt for information how to include this module - */ -static const char SysKonnectFileId[] = - "@(#)$Id: skvpd.c,v 1.37 2003/01/13 10:42:45 rschmidt Exp $ (C) SK"; - -#include "h/skdrv1st.h" -#include "h/sktypes.h" -#include "h/skdebug.h" -#include "h/skdrv2nd.h" - -/* - * Static functions - */ -#ifndef SK_KR_PROTO -static SK_VPD_PARA *vpd_find_para( - SK_AC *pAC, - const char *key, - SK_VPD_PARA *p); -#else /* SK_KR_PROTO */ -static SK_VPD_PARA *vpd_find_para(); -#endif /* SK_KR_PROTO */ - -/* - * waits for a completion of a VPD transfer - * The VPD transfer must complete within SK_TICKS_PER_SEC/16 - * - * returns 0: success, transfer completes - * error exit(9) with a error message - */ -static int VpdWait( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -int event) /* event to wait for (VPD_READ / VPD_write) completion*/ -{ - SK_U64 start_time; - SK_U16 state; - - SK_DBG_MSG(pAC,SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD wait for %s\n", event?"Write":"Read")); - start_time = SkOsGetTime(pAC); - do { - if (SkOsGetTime(pAC) - start_time > SK_TICKS_PER_SEC) { - - /* Bug fix AF: Thu Mar 28 2002 - * Do not call: VPD_STOP(pAC, IoC); - * A pending VPD read cycle can not be aborted by writing - * VPD_WRITE to the PCI_VPD_ADR_REG (VPD address register). - * Although the write threshold in the OUR-register protects - * VPD read only space from being overwritten this does not - * protect a VPD read from being `converted` into a VPD write - * operation (on the fly). As a consequence the VPD_STOP would - * delete VPD read only data. In case of any problems with the - * I2C bus we exit the loop here. The I2C read operation can - * not be aborted except by a reset (->LR). - */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_FATAL | SK_DBGCAT_ERR, - ("ERROR:VPD wait timeout\n")); - return(1); - } - - VPD_IN16(pAC, IoC, PCI_VPD_ADR_REG, &state); - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("state = %x, event %x\n",state,event)); - } while((int)(state & PCI_VPD_FLAG) == event); - - return(0); -} - -#ifdef SKDIAG - -/* - * Read the dword at address 'addr' from the VPD EEPROM. - * - * Needed Time: MIN 1,3 ms MAX 2,6 ms - * - * Note: The DWord is returned in the endianess of the machine the routine - * is running on. - * - * Returns the data read. - */ -SK_U32 VpdReadDWord( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -int addr) /* VPD address */ -{ - SK_U32 Rtv; - - /* start VPD read */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD read dword at 0x%x\n",addr)); - addr &= ~VPD_WRITE; /* ensure the R/W bit is set to read */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, (SK_U16)addr); - - /* ignore return code here */ - (void)VpdWait(pAC, IoC, VPD_READ); - - /* Don't swap here, it's a data stream of bytes */ - Rtv = 0; - - VPD_IN32(pAC, IoC, PCI_VPD_DAT_REG, &Rtv); - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD read dword data = 0x%x\n",Rtv)); - return(Rtv); -} - -#endif /* SKDIAG */ - -/* - * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdWriteStream( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int Addr, /* VPD start address */ -int Len) /* number of bytes to read / to write */ -{ - int i; - int j; - SK_U16 AdrReg; - int Rtv; - SK_U8 * pComp; /* Compare pointer */ - SK_U8 Data; /* Input Data for Compare */ - - /* Init Compare Pointer */ - pComp = (SK_U8 *) buf; - - for (i = 0; i < Len; i++, buf++) { - if ((i%sizeof(SK_U32)) == 0) { - /* - * At the begin of each cycle read the Data Reg - * So it is initialized even if only a few bytes - * are written. - */ - AdrReg = (SK_U16) Addr; - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - return(i); - } - } - - /* Write current Byte */ - VPD_OUT8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), - *(SK_U8*)buf); - - if (((i%sizeof(SK_U32)) == 3) || (i == (Len - 1))) { - /* New Address needs to be written to VPD_ADDR reg */ - AdrReg = (SK_U16) Addr; - Addr += sizeof(SK_U32); - AdrReg |= VPD_WRITE; /* WRITE operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_WRITE); - if (Rtv != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Write Timed Out\n")); - return(i - (i%sizeof(SK_U32))); - } - - /* - * Now re-read to verify - */ - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Verify Timed Out\n")); - return(i - (i%sizeof(SK_U32))); - } - - for (j = 0; j <= (int)(i%sizeof(SK_U32)); j++, pComp++) { - - VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + j, &Data); - - if (Data != *pComp) { - /* Verify Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("WriteStream Verify Error\n")); - return(i - (i%sizeof(SK_U32)) + j); - } - } - } - } - - return(Len); -} - - -/* - * Read one Stream of 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdReadStream( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int Addr, /* VPD start address */ -int Len) /* number of bytes to read / to write */ -{ - int i; - SK_U16 AdrReg; - int Rtv; - - for (i = 0; i < Len; i++, buf++) { - if ((i%sizeof(SK_U32)) == 0) { - /* New Address needs to be written to VPD_ADDR reg */ - AdrReg = (SK_U16) Addr; - Addr += sizeof(SK_U32); - AdrReg &= ~VPD_WRITE; /* READ operation */ - - VPD_OUT16(pAC, IoC, PCI_VPD_ADR_REG, AdrReg); - - /* Wait for termination */ - Rtv = VpdWait(pAC, IoC, VPD_READ); - if (Rtv != 0) { - return(i); - } - } - VPD_IN8(pAC, IoC, PCI_VPD_DAT_REG + (i%sizeof(SK_U32)), - (SK_U8 *)buf); - } - - return(Len); -} - -/* - * Read ore writes 'len' bytes of VPD data, starting at 'addr' from - * or to the I2C EEPROM. - * - * Returns number of bytes read / written. - */ -static int VpdTransferBlock( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC, /* IO Context */ -char *buf, /* data buffer */ -int addr, /* VPD start address */ -int len, /* number of bytes to read / to write */ -int dir) /* transfer direction may be VPD_READ or VPD_WRITE */ -{ - int Rtv; /* Return value */ - int vpd_rom_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD %s block, addr = 0x%x, len = %d\n", - dir ? "write" : "read", addr, len)); - - if (len == 0) - return(0); - - vpd_rom_size = pAC->vpd.rom_size; - - if (addr > vpd_rom_size - 4) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Address error: 0x%x, exp. < 0x%x\n", - addr, vpd_rom_size - 4)); - return(0); - } - - if (addr + len > vpd_rom_size) { - len = vpd_rom_size - addr; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Warning: len was cut to %d\n", len)); - } - - if (dir == VPD_READ) { - Rtv = VpdReadStream(pAC, IoC, buf, addr, len); - } - else { - Rtv = VpdWriteStream(pAC, IoC, buf, addr, len); - } - - return(Rtv); -} - -#ifdef SKDIAG - -/* - * Read 'len' bytes of VPD data, starting at 'addr'. - * - * Returns number of bytes read. - */ -int VpdReadBlock( -SK_AC *pAC, /* pAC pointer */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer were the data should be stored */ -int addr, /* start reading at the VPD address */ -int len) /* number of bytes to read */ -{ - return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_READ)); -} - -/* - * Write 'len' bytes of *but to the VPD EEPROM, starting at 'addr'. - * - * Returns number of bytes writes. - */ -int VpdWriteBlock( -SK_AC *pAC, /* pAC pointer */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer, holds the data to write */ -int addr, /* start writing at the VPD address */ -int len) /* number of bytes to write */ -{ - return(VpdTransferBlock(pAC, IoC, buf, addr, len, VPD_WRITE)); -} -#endif /* SKDIAG */ - -/* - * (re)initialize the VPD buffer - * - * Reads the VPD data from the EEPROM into the VPD buffer. - * Get the remaining read only and read / write space. - * - * return 0: success - * 1: fatal VPD error - */ -static int VpdInit( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - SK_VPD_PARA *r, rp; /* RW or RV */ - int i; - unsigned char x; - int vpd_size; - SK_U16 dev_id; - SK_U32 our_reg2; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, ("VpdInit .. ")); - - VPD_IN16(pAC, IoC, PCI_DEVICE_ID, &dev_id); - - VPD_IN32(pAC, IoC, PCI_OUR_REG_2, &our_reg2); - - pAC->vpd.rom_size = 256 << ((our_reg2 & PCI_VPD_ROM_SZ) >> 14); - - /* - * this function might get used before the hardware is initialized - * therefore we cannot always trust in GIChipId - */ - if (((pAC->vpd.v.vpd_status & VPD_VALID) == 0 && - dev_id != VPD_DEV_ID_GENESIS) || - ((pAC->vpd.v.vpd_status & VPD_VALID) != 0 && - !pAC->GIni.GIGenesis)) { - - /* for Yukon the VPD size is always 256 */ - vpd_size = VPD_SIZE_YUKON; - } - else { - /* Genesis uses the maximum ROM size up to 512 for VPD */ - if (pAC->vpd.rom_size > VPD_SIZE_GENESIS) { - vpd_size = VPD_SIZE_GENESIS; - } - else { - vpd_size = pAC->vpd.rom_size; - } - } - - /* read the VPD data into the VPD buffer */ - if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf, 0, vpd_size, VPD_READ) - != vpd_size) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("Block Read Error\n")); - return(1); - } - - pAC->vpd.vpd_size = vpd_size; - - /* Asus K8V Se Deluxe bugfix. Correct VPD content */ - /* MBo April 2004 */ - if (((unsigned char)pAC->vpd.vpd_buf[0x3f] == 0x38) && - ((unsigned char)pAC->vpd.vpd_buf[0x40] == 0x3c) && - ((unsigned char)pAC->vpd.vpd_buf[0x41] == 0x45)) { - printk("sk98lin: Asus mainboard with buggy VPD? " - "Correcting data.\n"); - pAC->vpd.vpd_buf[0x40] = 0x38; - } - - - /* find the end tag of the RO area */ - if (!(r = vpd_find_para(pAC, VPD_RV, &rp))) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: RV Tag not found\n")); - return(1); - } - - if (r->p_val + r->p_len > pAC->vpd.vpd_buf + vpd_size/2) { - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: Invalid VPD struct size\n")); - return(1); - } - pAC->vpd.v.vpd_free_ro = r->p_len - 1; - - /* test the checksum */ - for (i = 0, x = 0; (unsigned)i <= (unsigned)vpd_size/2 - r->p_len; i++) { - x += pAC->vpd.vpd_buf[i]; - } - - if (x != 0) { - /* checksum error */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("VPD Checksum Error\n")); - return(1); - } - - /* find and check the end tag of the RW area */ - if (!(r = vpd_find_para(pAC, VPD_RW, &rp))) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: RV Tag not found\n")); - return(1); - } - - if (r->p_val < pAC->vpd.vpd_buf + vpd_size/2) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: Invalid VPD struct size\n")); - return(1); - } - pAC->vpd.v.vpd_free_rw = r->p_len; - - /* everything seems to be ok */ - if (pAC->GIni.GIChipId != 0) { - pAC->vpd.v.vpd_status |= VPD_VALID; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_INIT, - ("done. Free RO = %d, Free RW = %d\n", - pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); - - return(0); -} - -/* - * find the Keyword 'key' in the VPD buffer and fills the - * parameter struct 'p' with it's values - * - * returns *p success - * 0: parameter was not found or VPD encoding error - */ -static SK_VPD_PARA *vpd_find_para( -SK_AC *pAC, /* common data base */ -const char *key, /* keyword to find (e.g. "MN") */ -SK_VPD_PARA *p) /* parameter description struct */ -{ - char *v ; /* points to VPD buffer */ - int max; /* Maximum Number of Iterations */ - - v = pAC->vpd.vpd_buf; - max = 128; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD find para %s .. ",key)); - - /* check mandatory resource type ID string (Product Name) */ - if (*v != (char)RES_ID) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Error: 0x%x missing\n", RES_ID)); - return NULL; - } - - if (strcmp(key, VPD_NAME) == 0) { - p->p_len = VPD_GET_RES_LEN(v); - p->p_val = VPD_GET_VAL(v); - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("found, len = %d\n", p->p_len)); - return(p); - } - - v += 3 + VPD_GET_RES_LEN(v) + 3; - for (;; ) { - if (SK_MEMCMP(key,v,2) == 0) { - p->p_len = VPD_GET_VPD_LEN(v); - p->p_val = VPD_GET_VAL(v); - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("found, len = %d\n",p->p_len)); - return(p); - } - - /* exit when reaching the "RW" Tag or the maximum of itera. */ - max--; - if (SK_MEMCMP(VPD_RW,v,2) == 0 || max == 0) { - break; - } - - if (SK_MEMCMP(VPD_RV,v,2) == 0) { - v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ - } - else { - v += 3 + VPD_GET_VPD_LEN(v); - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("scanning '%c%c' len = %d\n",v[0],v[1],v[2])); - } - -#ifdef DEBUG - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, ("not found\n")); - if (max == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Key/Len Encoding error\n")); - } -#endif /* DEBUG */ - return NULL; -} - -/* - * Move 'n' bytes. Begin with the last byte if 'n' is > 0, - * Start with the last byte if n is < 0. - * - * returns nothing - */ -static void vpd_move_para( -char *start, /* start of memory block */ -char *end, /* end of memory block to move */ -int n) /* number of bytes the memory block has to be moved */ -{ - char *p; - int i; /* number of byte copied */ - - if (n == 0) - return; - - i = (int) (end - start + 1); - if (n < 0) { - p = start + n; - while (i != 0) { - *p++ = *start++; - i--; - } - } - else { - p = end + n; - while (i != 0) { - *p-- = *end--; - i--; - } - } -} - -/* - * setup the VPD keyword 'key' at 'ip'. - * - * returns nothing - */ -static void vpd_insert_key( -const char *key, /* keyword to insert */ -const char *buf, /* buffer with the keyword value */ -int len, /* length of the value string */ -char *ip) /* inseration point */ -{ - SK_VPD_KEY *p; - - p = (SK_VPD_KEY *) ip; - p->p_key[0] = key[0]; - p->p_key[1] = key[1]; - p->p_len = (unsigned char) len; - SK_MEMCPY(&p->p_val,buf,len); -} - -/* - * Setup the VPD end tag "RV" / "RW". - * Also correct the remaining space variables vpd_free_ro / vpd_free_rw. - * - * returns 0: success - * 1: encoding error - */ -static int vpd_mod_endtag( -SK_AC *pAC, /* common data base */ -char *etp) /* end pointer input position */ -{ - SK_VPD_KEY *p; - unsigned char x; - int i; - int vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD modify endtag at 0x%x = '%c%c'\n",etp,etp[0],etp[1])); - - vpd_size = pAC->vpd.vpd_size; - - p = (SK_VPD_KEY *) etp; - - if (p->p_key[0] != 'R' || (p->p_key[1] != 'V' && p->p_key[1] != 'W')) { - /* something wrong here, encoding error */ - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR | SK_DBGCAT_FATAL, - ("Encoding Error: invalid end tag\n")); - return(1); - } - if (etp > pAC->vpd.vpd_buf + vpd_size/2) { - /* create "RW" tag */ - p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size-etp-3-1); - pAC->vpd.v.vpd_free_rw = (int) p->p_len; - i = pAC->vpd.v.vpd_free_rw; - etp += 3; - } - else { - /* create "RV" tag */ - p->p_len = (unsigned char)(pAC->vpd.vpd_buf+vpd_size/2-etp-3); - pAC->vpd.v.vpd_free_ro = (int) p->p_len - 1; - - /* setup checksum */ - for (i = 0, x = 0; i < vpd_size/2 - p->p_len; i++) { - x += pAC->vpd.vpd_buf[i]; - } - p->p_val = (char) 0 - x; - i = pAC->vpd.v.vpd_free_ro; - etp += 4; - } - while (i) { - *etp++ = 0x00; - i--; - } - - return(0); -} - -/* - * Insert a VPD keyword into the VPD buffer. - * - * The keyword 'key' is inserted at the position 'ip' in the - * VPD buffer. - * The keywords behind the input position will - * be moved. The VPD end tag "RV" or "RW" is generated again. - * - * returns 0: success - * 2: value string was cut - * 4: VPD full, keyword was not written - * 6: fatal VPD error - * - */ -static int VpdSetupPara( -SK_AC *pAC, /* common data base */ -const char *key, /* keyword to insert */ -const char *buf, /* buffer with the keyword value */ -int len, /* length of the keyword value */ -int type, /* VPD_RO_KEY or VPD_RW_KEY */ -int op) /* operation to do: ADD_KEY or OWR_KEY */ -{ - SK_VPD_PARA vp; - char *etp; /* end tag position */ - int free; /* remaining space in selected area */ - char *ip; /* input position inside the VPD buffer */ - int rtv; /* return code */ - int head; /* additional haeder bytes to move */ - int found; /* additinoal bytes if the keyword was found */ - int vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("VPD setup para key = %s, val = %s\n",key,buf)); - - vpd_size = pAC->vpd.vpd_size; - - rtv = 0; - ip = NULL; - if (type == VPD_RW_KEY) { - /* end tag is "RW" */ - free = pAC->vpd.v.vpd_free_rw; - etp = pAC->vpd.vpd_buf + (vpd_size - free - 1 - 3); - } - else { - /* end tag is "RV" */ - free = pAC->vpd.v.vpd_free_ro; - etp = pAC->vpd.vpd_buf + (vpd_size/2 - free - 4); - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Free RO = %d, Free RW = %d\n", - pAC->vpd.v.vpd_free_ro, pAC->vpd.v.vpd_free_rw)); - - head = 0; - found = 0; - if (op == OWR_KEY) { - if (vpd_find_para(pAC, key, &vp)) { - found = 3; - ip = vp.p_val - 3; - free += vp.p_len + 3; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Overwrite Key\n")); - } - else { - op = ADD_KEY; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_CTRL, - ("Add Key\n")); - } - } - if (op == ADD_KEY) { - ip = etp; - vp.p_len = 0; - head = 3; - } - - if (len + 3 > free) { - if (free < 7) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Buffer Overflow, keyword not written\n")); - return(4); - } - /* cut it again */ - len = free - 3; - rtv = 2; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Buffer Full, Keyword was cut\n")); - } - - vpd_move_para(ip + vp.p_len + found, etp+2, len-vp.p_len+head); - vpd_insert_key(key, buf, len, ip); - if (vpd_mod_endtag(pAC, etp + len - vp.p_len + head)) { - pAC->vpd.v.vpd_status &= ~VPD_VALID; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Encoding Error\n")); - return(6); - } - - return(rtv); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. - * - * return: A pointer to the vpd_status structure. The structure contains - * this fields. - */ -SK_VPD_STATUS *VpdStat( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - (void)VpdInit(pAC, IoC); - } - return(&pAC->vpd.v); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the VPD - * buffer if not already done. - * Scan the VPD buffer for VPD keywords and create the VPD - * keyword list by copying the keywords to 'buf', all after - * each other and terminated with a '\0'. - * - * Exceptions: o The Resource Type ID String (product name) is called "Name" - * o The VPD end tags 'RV' and 'RW' are not listed - * - * The number of copied keywords is counted in 'elements'. - * - * returns 0: success - * 2: buffer overfull, one or more keywords are missing - * 6: fatal VPD error - * - * example values after returning: - * - * buf = "Name\0PN\0EC\0MN\0SN\0CP\0VF\0VL\0YA\0" - * *len = 30 - * *elements = 9 - */ -int VpdKeys( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -char *buf, /* buffer where to copy the keywords */ -int *len, /* buffer length */ -int *elements) /* number of keywords returned */ -{ - char *v; - int n; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("list VPD keys .. ")); - *elements = 0; - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD Init Error, terminated\n")); - return(6); - } - } - - if ((signed)strlen(VPD_NAME) + 1 <= *len) { - v = pAC->vpd.vpd_buf; - strcpy(buf,VPD_NAME); - n = strlen(VPD_NAME) + 1; - buf += n; - *elements = 1; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("'%c%c' ",v[0],v[1])); - } - else { - *len = 0; - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_ERR, - ("buffer overflow\n")); - return(2); - } - - v += 3 + VPD_GET_RES_LEN(v) + 3; - for (;; ) { - /* exit when reaching the "RW" Tag */ - if (SK_MEMCMP(VPD_RW,v,2) == 0) { - break; - } - - if (SK_MEMCMP(VPD_RV,v,2) == 0) { - v += 3 + VPD_GET_VPD_LEN(v) + 3; /* skip VPD-W */ - continue; - } - - if (n+3 <= *len) { - SK_MEMCPY(buf,v,2); - buf += 2; - *buf++ = '\0'; - n += 3; - v += 3 + VPD_GET_VPD_LEN(v); - *elements += 1; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("'%c%c' ",v[0],v[1])); - } - else { - *len = n; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("buffer overflow\n")); - return(2); - } - } - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("\n")); - *len = n; - return(0); -} - - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. Search for the VPD keyword - * 'key' and copy its value to 'buf'. Add a terminating '\0'. - * If the value does not fit into the buffer cut it after - * 'len' - 1 bytes. - * - * returns 0: success - * 1: keyword not found - * 2: value string was cut - * 3: VPD transfer timeout - * 6: fatal VPD error - */ -int VpdRead( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -const char *key, /* keyword to read (e.g. "MN") */ -char *buf, /* buffer where to copy the keyword value */ -int *len) /* buffer length */ -{ - SK_VPD_PARA *p, vp; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, ("VPD read %s .. ", key)); - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { - if (p->p_len > (*(unsigned *)len)-1) { - p->p_len = *len - 1; - } - SK_MEMCPY(buf, p->p_val, p->p_len); - buf[p->p_len] = '\0'; - *len = p->p_len; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_RX, - ("%c%c%c%c.., len = %d\n", - buf[0],buf[1],buf[2],buf[3],*len)); - } - else { - *len = 0; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, ("not found\n")); - return(1); - } - return(0); -} - - -/* - * Check whether a given key may be written - * - * returns - * SK_TRUE Yes it may be written - * SK_FALSE No it may be written - */ -SK_BOOL VpdMayWrite( -char *key) /* keyword to write (allowed values "Yx", "Vx") */ -{ - if ((*key != 'Y' && *key != 'V') || - key[1] < '0' || key[1] > 'Z' || - (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { - - return(SK_FALSE); - } - return(SK_TRUE); -} - -/* - * Read the contents of the VPD EEPROM and copy it to the VPD - * buffer if not already done. Insert/overwrite the keyword 'key' - * in the VPD buffer. Cut the keyword value if it does not fit - * into the VPD read / write area. - * - * returns 0: success - * 2: value string was cut - * 3: VPD transfer timeout - * 4: VPD full, keyword was not written - * 5: keyword cannot be written - * 6: fatal VPD error - */ -int VpdWrite( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -const char *key, /* keyword to write (allowed values "Yx", "Vx") */ -const char *buf) /* buffer where the keyword value can be read from */ -{ - int len; /* length of the keyword to write */ - int rtv; /* return code */ - int rtv2; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, - ("VPD write %s = %s\n",key,buf)); - - if ((*key != 'Y' && *key != 'V') || - key[1] < '0' || key[1] > 'Z' || - (key[1] > '9' && key[1] < 'A') || strlen(key) != 2) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("illegal key tag, keyword not written\n")); - return(5); - } - - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - rtv = 0; - len = strlen(buf); - if (len > VPD_MAX_LEN) { - /* cut it */ - len = VPD_MAX_LEN; - rtv = 2; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("keyword too long, cut after %d bytes\n",VPD_MAX_LEN)); - } - if ((rtv2 = VpdSetupPara(pAC, key, buf, len, VPD_RW_KEY, OWR_KEY)) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD write error\n")); - return(rtv2); - } - - return(rtv); -} - -/* - * Read the contents of the VPD EEPROM and copy it to the - * VPD buffer if not already done. Remove the VPD keyword - * 'key' from the VPD buffer. - * Only the keywords in the read/write area can be deleted. - * Keywords in the read only area cannot be deleted. - * - * returns 0: success, keyword was removed - * 1: keyword not found - * 5: keyword cannot be deleted - * 6: fatal VPD error - */ -int VpdDelete( -SK_AC *pAC, /* common data base */ -SK_IOC IoC, /* IO Context */ -char *key) /* keyword to read (e.g. "MN") */ -{ - SK_VPD_PARA *p, vp; - char *etp; - int vpd_size; - - vpd_size = pAC->vpd.vpd_size; - - SK_DBG_MSG(pAC,SK_DBGMOD_VPD,SK_DBGCAT_TX,("VPD delete key %s\n",key)); - if ((pAC->vpd.v.vpd_status & VPD_VALID) == 0) { - if (VpdInit(pAC, IoC) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD init error\n")); - return(6); - } - } - - if ((p = vpd_find_para(pAC, key, &vp)) != NULL) { - if (p->p_val < pAC->vpd.vpd_buf + vpd_size/2) { - /* try to delete read only keyword */ - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("cannot delete RO keyword\n")); - return(5); - } - - etp = pAC->vpd.vpd_buf + (vpd_size-pAC->vpd.v.vpd_free_rw-1-3); - - vpd_move_para(vp.p_val+vp.p_len, etp+2, - - ((int)(vp.p_len + 3))); - if (vpd_mod_endtag(pAC, etp - vp.p_len - 3)) { - pAC->vpd.v.vpd_status &= ~VPD_VALID; - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("VPD encoding error\n")); - return(6); - } - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("keyword not found\n")); - return(1); - } - - return(0); -} - -/* - * If the VPD buffer contains valid data write the VPD - * read/write area back to the VPD EEPROM. - * - * returns 0: success - * 3: VPD transfer timeout - */ -int VpdUpdate( -SK_AC *pAC, /* Adapters context */ -SK_IOC IoC) /* IO Context */ -{ - int vpd_size; - - vpd_size = pAC->vpd.vpd_size; - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("VPD update .. ")); - if ((pAC->vpd.v.vpd_status & VPD_VALID) != 0) { - if (VpdTransferBlock(pAC, IoC, pAC->vpd.vpd_buf + vpd_size/2, - vpd_size/2, vpd_size/2, VPD_WRITE) != vpd_size/2) { - - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_ERR, - ("transfer timed out\n")); - return(3); - } - } - SK_DBG_MSG(pAC, SK_DBGMOD_VPD, SK_DBGCAT_TX, ("done\n")); - return(0); -} - diff --git a/drivers/net/sk98lin/skxmac2.c b/drivers/net/sk98lin/skxmac2.c deleted file mode 100644 index b4e75022a657..000000000000 --- a/drivers/net/sk98lin/skxmac2.c +++ /dev/null @@ -1,4160 +0,0 @@ -/****************************************************************************** - * - * Name: skxmac2.c - * Project: Gigabit Ethernet Adapters, Common Modules - * Version: $Revision: 1.102 $ - * Date: $Date: 2003/10/02 16:53:58 $ - * Purpose: Contains functions to initialize the MACs and PHYs - * - ******************************************************************************/ - -/****************************************************************************** - * - * (C)Copyright 1998-2002 SysKonnect. - * (C)Copyright 2002-2003 Marvell. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * The information in this file is provided "AS IS" without warranty. - * - ******************************************************************************/ - -#include "h/skdrv1st.h" -#include "h/skdrv2nd.h" - -/* typedefs *******************************************************************/ - -/* BCOM PHY magic pattern list */ -typedef struct s_PhyHack { - int PhyReg; /* Phy register */ - SK_U16 PhyVal; /* Value to write */ -} BCOM_HACK; - -/* local variables ************************************************************/ - -#if (defined(DEBUG) || ((!defined(LINT)) && (!defined(SK_SLIM)))) -static const char SysKonnectFileId[] = - "@(#) $Id: skxmac2.c,v 1.102 2003/10/02 16:53:58 rschmidt Exp $ (C) Marvell."; -#endif - -#ifdef GENESIS -static BCOM_HACK BcomRegA1Hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, { 0x17, 0x0013 }, - { 0x15, 0x0404 }, { 0x17, 0x8006 }, { 0x15, 0x0132 }, { 0x17, 0x8006 }, - { 0x15, 0x0232 }, { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, - { 0, 0 } -}; -static BCOM_HACK BcomRegC0Hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, { 0x17, 0x0013 }, - { 0x15, 0x0A04 }, { 0x18, 0x0420 }, - { 0, 0 } -}; -#endif - -/* function prototypes ********************************************************/ -#ifdef GENESIS -static void SkXmInitPhyXmac(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkXmInitPhyBcom(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkXmAutoNegDoneXmac(SK_AC*, SK_IOC, int); -static int SkXmAutoNegDoneBcom(SK_AC*, SK_IOC, int); -#endif /* GENESIS */ -#ifdef YUKON -static void SkGmInitPhyMarv(SK_AC*, SK_IOC, int, SK_BOOL); -static int SkGmAutoNegDoneMarv(SK_AC*, SK_IOC, int); -#endif /* YUKON */ -#ifdef OTHER_PHY -static void SkXmInitPhyLone(SK_AC*, SK_IOC, int, SK_BOOL); -static void SkXmInitPhyNat (SK_AC*, SK_IOC, int, SK_BOOL); -static int SkXmAutoNegDoneLone(SK_AC*, SK_IOC, int); -static int SkXmAutoNegDoneNat (SK_AC*, SK_IOC, int); -#endif /* OTHER_PHY */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmPhyRead() - Read from XMAC PHY register - * - * Description: reads a 16-bit word from XMAC PHY or ext. PHY - * - * Returns: - * nothing - */ -void SkXmPhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 SK_FAR *pVal) /* Pointer to Value */ -{ - SK_U16 Mmu; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - /* write the PHY register's address */ - XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); - - /* get the PHY register's value */ - XM_IN16(IoC, Port, XM_PHY_DATA, pVal); - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Ready' is set */ - } while ((Mmu & XM_MMU_PHY_RDY) == 0); - - /* get the PHY register's value */ - XM_IN16(IoC, Port, XM_PHY_DATA, pVal); - } -} /* SkXmPhyRead */ - - -/****************************************************************************** - * - * SkXmPhyWrite() - Write to XMAC PHY register - * - * Description: writes a 16-bit word to XMAC PHY or ext. PHY - * - * Returns: - * nothing - */ -void SkXmPhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - SK_U16 Mmu; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Busy' is cleared */ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); - } - - /* write the PHY register's address */ - XM_OUT16(IoC, Port, XM_PHY_ADDR, PhyReg | pPrt->PhyAddr); - - /* write the PHY register's value */ - XM_OUT16(IoC, Port, XM_PHY_DATA, Val); - - if (pPrt->PhyType != SK_PHY_XMAC) { - do { - XM_IN16(IoC, Port, XM_MMU_CMD, &Mmu); - /* wait until 'Busy' is cleared */ - } while ((Mmu & XM_MMU_PHY_BUSY) != 0); - } -} /* SkXmPhyWrite */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmPhyRead() - Read from GPHY register - * - * Description: reads a 16-bit word from GPHY through MDIO - * - * Returns: - * nothing - */ -void SkGmPhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 SK_FAR *pVal) /* Pointer to Value */ -{ - SK_U16 Ctrl; - SK_GEPORT *pPrt; -#ifdef VCPU - u_long SimCyle; - u_long SimLowTime; - - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "SkGmPhyRead(%u), SimCyle=%u, SimLowTime=%u\n", - PhyReg, SimCyle, SimLowTime); -#endif /* VCPU */ - - pPrt = &pAC->GIni.GP[Port]; - - /* set PHY-Register offset and 'Read' OpCode (= 1) */ - *pVal = (SK_U16)(GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | - GM_SMI_CT_REG_AD(PhyReg) | GM_SMI_CT_OP_RD); - - GM_OUT16(IoC, Port, GM_SMI_CTRL, *pVal); - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* additional check for MDC/MDIO activity */ - if ((Ctrl & GM_SMI_CT_BUSY) == 0) { - *pVal = 0; - return; - } - - *pVal |= GM_SMI_CT_BUSY; - - do { -#ifdef VCPU - VCPUwaitTime(1000); -#endif /* VCPU */ - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* wait until 'ReadValid' is set */ - } while (Ctrl == *pVal); - - /* get the PHY register's value */ - GM_IN16(IoC, Port, GM_SMI_DATA, pVal); - -#ifdef VCPU - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", - SimCyle, SimLowTime); -#endif /* VCPU */ - -} /* SkGmPhyRead */ - - -/****************************************************************************** - * - * SkGmPhyWrite() - Write to GPHY register - * - * Description: writes a 16-bit word to GPHY through MDIO - * - * Returns: - * nothing - */ -void SkGmPhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - SK_U16 Ctrl; - SK_GEPORT *pPrt; -#ifdef VCPU - SK_U32 DWord; - u_long SimCyle; - u_long SimLowTime; - - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "SkGmPhyWrite(Reg=%u, Val=0x%04x), SimCyle=%u, SimLowTime=%u\n", - PhyReg, Val, SimCyle, SimLowTime); -#endif /* VCPU */ - - pPrt = &pAC->GIni.GP[Port]; - - /* write the PHY register's value */ - GM_OUT16(IoC, Port, GM_SMI_DATA, Val); - - /* set PHY-Register offset and 'Write' OpCode (= 0) */ - Val = GM_SMI_CT_PHY_AD(pPrt->PhyAddr) | GM_SMI_CT_REG_AD(PhyReg); - - GM_OUT16(IoC, Port, GM_SMI_CTRL, Val); - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* additional check for MDC/MDIO activity */ - if ((Ctrl & GM_SMI_CT_BUSY) == 0) { - return; - } - - Val |= GM_SMI_CT_BUSY; - - do { -#ifdef VCPU - /* read Timer value */ - SK_IN32(IoC, B2_TI_VAL, &DWord); - - VCPUwaitTime(1000); -#endif /* VCPU */ - - GM_IN16(IoC, Port, GM_SMI_CTRL, &Ctrl); - - /* wait until 'Busy' is cleared */ - } while (Ctrl == Val); - -#ifdef VCPU - VCPUgetTime(&SimCyle, &SimLowTime); - VCPUprintf(0, "VCPUgetTime(), SimCyle=%u, SimLowTime=%u\n", - SimCyle, SimLowTime); -#endif /* VCPU */ - -} /* SkGmPhyWrite */ -#endif /* YUKON */ - - -#ifdef SK_DIAG -/****************************************************************************** - * - * SkGePhyRead() - Read from PHY register - * - * Description: calls a read PHY routine dep. on board type - * - * Returns: - * nothing - */ -void SkGePhyRead( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 *pVal) /* Pointer to Value */ -{ - void (*r_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 *pVal); - - if (pAC->GIni.GIGenesis) { - r_func = SkXmPhyRead; - } - else { - r_func = SkGmPhyRead; - } - - r_func(pAC, IoC, Port, PhyReg, pVal); -} /* SkGePhyRead */ - - -/****************************************************************************** - * - * SkGePhyWrite() - Write to PHY register - * - * Description: calls a write PHY routine dep. on board type - * - * Returns: - * nothing - */ -void SkGePhyWrite( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* I/O Context */ -int Port, /* Port Index (MAC_1 + n) */ -int PhyReg, /* Register Address (Offset) */ -SK_U16 Val) /* Value */ -{ - void (*w_func)(SK_AC *pAC, SK_IOC IoC, int Port, int Reg, SK_U16 Val); - - if (pAC->GIni.GIGenesis) { - w_func = SkXmPhyWrite; - } - else { - w_func = SkGmPhyWrite; - } - - w_func(pAC, IoC, Port, PhyReg, Val); -} /* SkGePhyWrite */ -#endif /* SK_DIAG */ - - -/****************************************************************************** - * - * SkMacPromiscMode() - Enable / Disable Promiscuous Mode - * - * Description: - * enables / disables promiscuous mode by setting Mode Register (XMAC) or - * Receive Control Register (GMAC) dep. on board type - * - * Returns: - * nothing - */ -void SkMacPromiscMode( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ -#ifdef YUKON - SK_U16 RcReg; -#endif -#ifdef GENESIS - SK_U32 MdReg; -#endif - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - /* enable or disable promiscuous mode */ - if (Enable) { - MdReg |= XM_MD_ENA_PROM; - } - else { - MdReg &= ~XM_MD_ENA_PROM; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); - - /* enable or disable unicast and multicast filtering */ - if (Enable) { - RcReg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - } - else { - RcReg |= (GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - } - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); - } -#endif /* YUKON */ - -} /* SkMacPromiscMode*/ - - -/****************************************************************************** - * - * SkMacHashing() - Enable / Disable Hashing - * - * Description: - * enables / disables hashing by setting Mode Register (XMAC) or - * Receive Control Register (GMAC) dep. on board type - * - * Returns: - * nothing - */ -void SkMacHashing( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ -#ifdef YUKON - SK_U16 RcReg; -#endif -#ifdef GENESIS - SK_U32 MdReg; -#endif - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - /* enable or disable hashing */ - if (Enable) { - MdReg |= XM_MD_ENA_HASH; - } - else { - MdReg &= ~XM_MD_ENA_HASH; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - GM_IN16(IoC, Port, GM_RX_CTRL, &RcReg); - - /* enable or disable multicast filtering */ - if (Enable) { - RcReg |= GM_RXCR_MCF_ENA; - } - else { - RcReg &= ~GM_RXCR_MCF_ENA; - } - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, RcReg); - } -#endif /* YUKON */ - -} /* SkMacHashing*/ - - -#ifdef SK_DIAG -/****************************************************************************** - * - * SkXmSetRxCmd() - Modify the value of the XMAC's Rx Command Register - * - * Description: - * The features - * - FCS stripping, SK_STRIP_FCS_ON/OFF - * - pad byte stripping, SK_STRIP_PAD_ON/OFF - * - don't set XMR_FS_ERR in status SK_LENERR_OK_ON/OFF - * for inrange length error frames - * - don't set XMR_FS_ERR in status SK_BIG_PK_OK_ON/OFF - * for frames > 1514 bytes - * - enable Rx of own packets SK_SELF_RX_ON/OFF - * - * for incoming packets may be enabled/disabled by this function. - * Additional modes may be added later. - * Multiple modes can be enabled/disabled at the same time. - * The new configuration is written to the Rx Command register immediately. - * - * Returns: - * nothing - */ -static void SkXmSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, - SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ -{ - SK_U16 OldRxCmd; - SK_U16 RxCmd; - - XM_IN16(IoC, Port, XM_RX_CMD, &OldRxCmd); - - RxCmd = OldRxCmd; - - switch (Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) { - case SK_STRIP_FCS_ON: - RxCmd |= XM_RX_STRIP_FCS; - break; - case SK_STRIP_FCS_OFF: - RxCmd &= ~XM_RX_STRIP_FCS; - break; - } - - switch (Mode & (SK_STRIP_PAD_ON | SK_STRIP_PAD_OFF)) { - case SK_STRIP_PAD_ON: - RxCmd |= XM_RX_STRIP_PAD; - break; - case SK_STRIP_PAD_OFF: - RxCmd &= ~XM_RX_STRIP_PAD; - break; - } - - switch (Mode & (SK_LENERR_OK_ON | SK_LENERR_OK_OFF)) { - case SK_LENERR_OK_ON: - RxCmd |= XM_RX_LENERR_OK; - break; - case SK_LENERR_OK_OFF: - RxCmd &= ~XM_RX_LENERR_OK; - break; - } - - switch (Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) { - case SK_BIG_PK_OK_ON: - RxCmd |= XM_RX_BIG_PK_OK; - break; - case SK_BIG_PK_OK_OFF: - RxCmd &= ~XM_RX_BIG_PK_OK; - break; - } - - switch (Mode & (SK_SELF_RX_ON | SK_SELF_RX_OFF)) { - case SK_SELF_RX_ON: - RxCmd |= XM_RX_SELF_RX; - break; - case SK_SELF_RX_OFF: - RxCmd &= ~XM_RX_SELF_RX; - break; - } - - /* Write the new mode to the Rx command register if required */ - if (OldRxCmd != RxCmd) { - XM_OUT16(IoC, Port, XM_RX_CMD, RxCmd); - } -} /* SkXmSetRxCmd */ - - -/****************************************************************************** - * - * SkGmSetRxCmd() - Modify the value of the GMAC's Rx Control Register - * - * Description: - * The features - * - FCS (CRC) stripping, SK_STRIP_FCS_ON/OFF - * - don't set GMR_FS_LONG_ERR SK_BIG_PK_OK_ON/OFF - * for frames > 1514 bytes - * - enable Rx of own packets SK_SELF_RX_ON/OFF - * - * for incoming packets may be enabled/disabled by this function. - * Additional modes may be added later. - * Multiple modes can be enabled/disabled at the same time. - * The new configuration is written to the Rx Command register immediately. - * - * Returns: - * nothing - */ -static void SkGmSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Mode is SK_STRIP_FCS_ON/OFF, SK_STRIP_PAD_ON/OFF, - SK_LENERR_OK_ON/OFF, or SK_BIG_PK_OK_ON/OFF */ -{ - SK_U16 OldRxCmd; - SK_U16 RxCmd; - - if ((Mode & (SK_STRIP_FCS_ON | SK_STRIP_FCS_OFF)) != 0) { - - GM_IN16(IoC, Port, GM_RX_CTRL, &OldRxCmd); - - RxCmd = OldRxCmd; - - if ((Mode & SK_STRIP_FCS_ON) != 0) { - RxCmd |= GM_RXCR_CRC_DIS; - } - else { - RxCmd &= ~GM_RXCR_CRC_DIS; - } - /* Write the new mode to the Rx control register if required */ - if (OldRxCmd != RxCmd) { - GM_OUT16(IoC, Port, GM_RX_CTRL, RxCmd); - } - } - - if ((Mode & (SK_BIG_PK_OK_ON | SK_BIG_PK_OK_OFF)) != 0) { - - GM_IN16(IoC, Port, GM_SERIAL_MODE, &OldRxCmd); - - RxCmd = OldRxCmd; - - if ((Mode & SK_BIG_PK_OK_ON) != 0) { - RxCmd |= GM_SMOD_JUMBO_ENA; - } - else { - RxCmd &= ~GM_SMOD_JUMBO_ENA; - } - /* Write the new mode to the Rx control register if required */ - if (OldRxCmd != RxCmd) { - GM_OUT16(IoC, Port, GM_SERIAL_MODE, RxCmd); - } - } -} /* SkGmSetRxCmd */ - - -/****************************************************************************** - * - * SkMacSetRxCmd() - Modify the value of the MAC's Rx Control Register - * - * Description: modifies the MAC's Rx Control reg. dep. on board type - * - * Returns: - * nothing - */ -void SkMacSetRxCmd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int Mode) /* Rx Mode */ -{ - if (pAC->GIni.GIGenesis) { - - SkXmSetRxCmd(pAC, IoC, Port, Mode); - } - else { - - SkGmSetRxCmd(pAC, IoC, Port, Mode); - } - -} /* SkMacSetRxCmd */ - - -/****************************************************************************** - * - * SkMacCrcGener() - Enable / Disable CRC Generation - * - * Description: enables / disables CRC generation dep. on board type - * - * Returns: - * nothing - */ -void SkMacCrcGener( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U16 Word; - - if (pAC->GIni.GIGenesis) { - - XM_IN16(IoC, Port, XM_TX_CMD, &Word); - - if (Enable) { - Word &= ~XM_TX_NO_CRC; - } - else { - Word |= XM_TX_NO_CRC; - } - /* setup Tx Command Register */ - XM_OUT16(IoC, Port, XM_TX_CMD, Word); - } - else { - - GM_IN16(IoC, Port, GM_TX_CTRL, &Word); - - if (Enable) { - Word &= ~GM_TXCR_CRC_DIS; - } - else { - Word |= GM_TXCR_CRC_DIS; - } - /* setup Tx Control Register */ - GM_OUT16(IoC, Port, GM_TX_CTRL, Word); - } - -} /* SkMacCrcGener*/ - -#endif /* SK_DIAG */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmClrExactAddr() - Clear Exact Match Address Registers - * - * Description: - * All Exact Match Address registers of the XMAC 'Port' will be - * cleared starting with 'StartNum' up to (and including) the - * Exact Match address number of 'StopNum'. - * - * Returns: - * nothing - */ -void SkXmClrExactAddr( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -int StartNum, /* Begin with this Address Register Index (0..15) */ -int StopNum) /* Stop after finished with this Register Idx (0..15) */ -{ - int i; - SK_U16 ZeroAddr[3] = {0x0000, 0x0000, 0x0000}; - - if ((unsigned)StartNum > 15 || (unsigned)StopNum > 15 || - StartNum > StopNum) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E001, SKERR_HWI_E001MSG); - return; - } - - for (i = StartNum; i <= StopNum; i++) { - XM_OUTADDR(IoC, Port, XM_EXM(i), &ZeroAddr[0]); - } -} /* SkXmClrExactAddr */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkMacFlushTxFifo() - Flush the MAC's transmit FIFO - * - * Description: - * Flush the transmit FIFO of the MAC specified by the index 'Port' - * - * Returns: - * nothing - */ -void SkMacFlushTxFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -#ifdef GENESIS - SK_U32 MdReg; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FTF); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* no way to flush the FIFO we have to issue a reset */ - /* TBD */ - } -#endif /* YUKON */ - -} /* SkMacFlushTxFifo */ - - -/****************************************************************************** - * - * SkMacFlushRxFifo() - Flush the MAC's receive FIFO - * - * Description: - * Flush the receive FIFO of the MAC specified by the index 'Port' - * - * Returns: - * nothing - */ -static void SkMacFlushRxFifo( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -#ifdef GENESIS - SK_U32 MdReg; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - XM_OUT32(IoC, Port, XM_MODE, MdReg | XM_MD_FRF); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* no way to flush the FIFO we have to issue a reset */ - /* TBD */ - } -#endif /* YUKON */ - -} /* SkMacFlushRxFifo */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmSoftRst() - Do a XMAC software reset - * - * Description: - * The PHY registers should not be destroyed during this - * kind of software reset. Therefore the XMAC Software Reset - * (XM_GP_RES_MAC bit in XM_GP_PORT) must not be used! - * - * The software reset is done by - * - disabling the Rx and Tx state machine, - * - resetting the statistics module, - * - clear all other significant XMAC Mode, - * Command, and Control Registers - * - clearing the Hash Register and the - * Exact Match Address registers, and - * - flushing the XMAC's Rx and Tx FIFOs. - * - * Note: - * Another requirement when stopping the XMAC is to - * avoid sending corrupted frames on the network. - * Disabling the Tx state machine will NOT interrupt - * the currently transmitted frame. But we must take care - * that the Tx FIFO is cleared AFTER the current frame - * is complete sent to the network. - * - * It takes about 12ns to send a frame with 1538 bytes. - * One PCI clock goes at least 15ns (66MHz). Therefore - * after reading XM_GP_PORT back, we are sure that the - * transmitter is disabled AND idle. And this means - * we may flush the transmit FIFO now. - * - * Returns: - * nothing - */ -static void SkXmSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 ZeroAddr[4] = {0x0000, 0x0000, 0x0000, 0x0000}; - - /* reset the statistics module */ - XM_OUT32(IoC, Port, XM_GP_PORT, XM_GP_RES_STAT); - - /* disable all XMAC IRQs */ - XM_OUT16(IoC, Port, XM_IMSK, 0xffff); - - XM_OUT32(IoC, Port, XM_MODE, 0); /* clear Mode Reg */ - - XM_OUT16(IoC, Port, XM_TX_CMD, 0); /* reset TX CMD Reg */ - XM_OUT16(IoC, Port, XM_RX_CMD, 0); /* reset RX CMD Reg */ - - /* disable all PHY IRQs */ - switch (pAC->GIni.GP[Port].PhyType) { - case SK_PHY_BCOM: - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); - break; - case SK_PHY_NAT: - /* todo: National - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ - break; -#endif /* OTHER_PHY */ - } - - /* clear the Hash Register */ - XM_OUTHASH(IoC, Port, XM_HSM, &ZeroAddr); - - /* clear the Exact Match Address registers */ - SkXmClrExactAddr(pAC, IoC, Port, 0, 15); - - /* clear the Source Check Address registers */ - XM_OUTHASH(IoC, Port, XM_SRC_CHK, &ZeroAddr); - -} /* SkXmSoftRst */ - - -/****************************************************************************** - * - * SkXmHardRst() - Do a XMAC hardware reset - * - * Description: - * The XMAC of the specified 'Port' and all connected devices - * (PHY and SERDES) will receive a reset signal on its *Reset pins. - * External PHYs must be reset by clearing a bit in the GPIO register - * (Timing requirements: Broadcom: 400ns, Level One: none, National: 80ns). - * - * ATTENTION: - * It is absolutely necessary to reset the SW_RST Bit first - * before calling this function. - * - * Returns: - * nothing - */ -static void SkXmHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 Reg; - int i; - int TOut; - SK_U16 Word; - - for (i = 0; i < 4; i++) { - /* TX_MFF_CTRL1 has 32 bits, but only the lowest 16 bits are used */ - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - - TOut = 0; - do { - if (TOut++ > 10000) { - /* - * Adapter seems to be in RESET state. - * Registers cannot be written. - */ - return; - } - - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_SET_MAC_RST); - - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &Word); - - } while ((Word & MFF_SET_MAC_RST) == 0); - } - - /* For external PHYs there must be special handling */ - if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { - - SK_IN32(IoC, B2_GP_IO, &Reg); - - if (Port == 0) { - Reg |= GP_DIR_0; /* set to output */ - Reg &= ~GP_IO_0; /* set PHY reset (active low) */ - } - else { - Reg |= GP_DIR_2; /* set to output */ - Reg &= ~GP_IO_2; /* set PHY reset (active low) */ - } - /* reset external PHY */ - SK_OUT32(IoC, B2_GP_IO, Reg); - - /* short delay */ - SK_IN32(IoC, B2_GP_IO, &Reg); - } -} /* SkXmHardRst */ - - -/****************************************************************************** - * - * SkXmClearRst() - Release the PHY & XMAC reset - * - * Description: - * - * Returns: - * nothing - */ -static void SkXmClearRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 DWord; - - /* clear HW reset */ - SK_OUT16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - - if (pAC->GIni.GP[Port].PhyType != SK_PHY_XMAC) { - - SK_IN32(IoC, B2_GP_IO, &DWord); - - if (Port == 0) { - DWord |= (GP_DIR_0 | GP_IO_0); /* set to output */ - } - else { - DWord |= (GP_DIR_2 | GP_IO_2); /* set to output */ - } - /* Clear PHY reset */ - SK_OUT32(IoC, B2_GP_IO, DWord); - - /* Enable GMII interface */ - XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_GMII_MD); - } -} /* SkXmClearRst */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmSoftRst() - Do a GMAC software reset - * - * Description: - * The GPHY registers should not be destroyed during this - * kind of software reset. - * - * Returns: - * nothing - */ -static void SkGmSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 EmptyHash[4] = {0x0000, 0x0000, 0x0000, 0x0000}; - SK_U16 RxCtrl; - - /* reset the statistics module */ - - /* disable all GMAC IRQs */ - SK_OUT8(IoC, GMAC_IRQ_MSK, 0); - - /* disable all PHY IRQs */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); - - /* clear the Hash Register */ - GM_OUTHASH(IoC, Port, GM_MC_ADDR_H1, EmptyHash); - - /* Enable Unicast and Multicast filtering */ - GM_IN16(IoC, Port, GM_RX_CTRL, &RxCtrl); - - GM_OUT16(IoC, Port, GM_RX_CTRL, - (SK_U16)(RxCtrl | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA)); - -} /* SkGmSoftRst */ - - -/****************************************************************************** - * - * SkGmHardRst() - Do a GMAC hardware reset - * - * Description: - * - * Returns: - * nothing - */ -static void SkGmHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 DWord; - - /* WA code for COMA mode */ - if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { - - SK_IN32(IoC, B2_GP_IO, &DWord); - - DWord |= (GP_DIR_9 | GP_IO_9); - - /* set PHY reset */ - SK_OUT32(IoC, B2_GP_IO, DWord); - } - - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), GPC_RST_SET); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); - -} /* SkGmHardRst */ - - -/****************************************************************************** - * - * SkGmClearRst() - Release the GPHY & GMAC reset - * - * Description: - * - * Returns: - * nothing - */ -static void SkGmClearRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U32 DWord; - -#ifdef XXX - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_CLR); - - /* set GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_RST_SET); -#endif /* XXX */ - - /* WA code for COMA mode */ - if (pAC->GIni.GIYukonLite && - pAC->GIni.GIChipRev >= CHIP_REV_YU_LITE_A3) { - - SK_IN32(IoC, B2_GP_IO, &DWord); - - DWord |= GP_DIR_9; /* set to output */ - DWord &= ~GP_IO_9; /* clear PHY reset (active high) */ - - /* clear PHY reset */ - SK_OUT32(IoC, B2_GP_IO, DWord); - } - - /* set HWCFG_MODE */ - DWord = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | - GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE | - (pAC->GIni.GICopperType ? GPC_HWCFG_GMII_COP : - GPC_HWCFG_GMII_FIB); - - /* set GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_SET); - - /* release GPHY Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GPHY_CTRL), DWord | GPC_RST_CLR); - -#ifdef VCPU - VCpuWait(9000); -#endif /* VCPU */ - - /* clear GMAC Control reset */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); - -#ifdef VCPU - VCpuWait(2000); - - SK_IN32(IoC, MR_ADDR(Port, GPHY_CTRL), &DWord); - - SK_IN32(IoC, B0_ISRC, &DWord); -#endif /* VCPU */ - -} /* SkGmClearRst */ -#endif /* YUKON */ - - -/****************************************************************************** - * - * SkMacSoftRst() - Do a MAC software reset - * - * Description: calls a MAC software reset routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacSoftRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - /* disable receiver and transmitter */ - SkMacRxTxDisable(pAC, IoC, Port); - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SkXmSoftRst(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmSoftRst(pAC, IoC, Port); - } -#endif /* YUKON */ - - /* flush the MAC's Rx and Tx FIFOs */ - SkMacFlushTxFifo(pAC, IoC, Port); - - SkMacFlushRxFifo(pAC, IoC, Port); - - pPrt->PState = SK_PRT_STOP; - -} /* SkMacSoftRst */ - - -/****************************************************************************** - * - * SkMacHardRst() - Do a MAC hardware reset - * - * Description: calls a MAC hardware reset routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacHardRst( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - SkXmHardRst(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmHardRst(pAC, IoC, Port); - } -#endif /* YUKON */ - - pAC->GIni.GP[Port].PState = SK_PRT_RESET; - -} /* SkMacHardRst */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmInitMac() - Initialize the XMAC II - * - * Description: - * Initialize the XMAC of the specified port. - * The XMAC must be reset or stopped before calling this function. - * - * Note: - * The XMAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * nothing - */ -void SkXmInitMac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int i; - SK_U16 SWord; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PState == SK_PRT_STOP) { - /* Port State: SK_PRT_STOP */ - /* Verify that the reset bit is cleared */ - SK_IN16(IoC, MR_ADDR(Port, TX_MFF_CTRL1), &SWord); - - if ((SWord & MFF_SET_MAC_RST) != 0) { - /* PState does not match HW state */ - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); - /* Correct it */ - pPrt->PState = SK_PRT_RESET; - } - } - - if (pPrt->PState == SK_PRT_RESET) { - - SkXmClearRst(pAC, IoC, Port); - - if (pPrt->PhyType != SK_PHY_XMAC) { - /* read Id from external PHY (all have the same address) */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_ID1, &pPrt->PhyId1); - - /* - * Optimize MDIO transfer by suppressing preamble. - * Must be done AFTER first access to BCOM chip. - */ - XM_IN16(IoC, Port, XM_MMU_CMD, &SWord); - - XM_OUT16(IoC, Port, XM_MMU_CMD, SWord | XM_MMU_NO_PRE); - - if (pPrt->PhyId1 == PHY_BCOM_ID1_C0) { - /* - * Workaround BCOM Errata for the C0 type. - * Write magic patterns to reserved registers. - */ - i = 0; - while (BcomRegC0Hack[i].PhyReg != 0) { - SkXmPhyWrite(pAC, IoC, Port, BcomRegC0Hack[i].PhyReg, - BcomRegC0Hack[i].PhyVal); - i++; - } - } - else if (pPrt->PhyId1 == PHY_BCOM_ID1_A1) { - /* - * Workaround BCOM Errata for the A1 type. - * Write magic patterns to reserved registers. - */ - i = 0; - while (BcomRegA1Hack[i].PhyReg != 0) { - SkXmPhyWrite(pAC, IoC, Port, BcomRegA1Hack[i].PhyReg, - BcomRegA1Hack[i].PhyVal); - i++; - } - } - - /* - * Workaround BCOM Errata (#10523) for all BCom PHYs. - * Disable Power Management after reset. - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); - - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(SWord | PHY_B_AC_DIS_PM)); - - /* PHY LED initialization is done in SkGeXmitLED() */ - } - - /* Dummy read the Interrupt source register */ - XM_IN16(IoC, Port, XM_ISRC, &SWord); - - /* - * The auto-negotiation process starts immediately after - * clearing the reset. The auto-negotiation process should be - * started by the SIRQ, therefore stop it here immediately. - */ - SkMacInitPhy(pAC, IoC, Port, SK_FALSE); - -#ifdef TEST_ONLY - /* temp. code: enable signal detect */ - /* WARNING: do not override GMII setting above */ - XM_OUT16(IoC, Port, XM_HW_CFG, XM_HW_COM4SIG); -#endif - } - - /* - * configure the XMACs Station Address - * B2_MAC_2 = xx xx xx xx xx x1 is programmed to XMAC A - * B2_MAC_3 = xx xx xx xx xx x2 is programmed to XMAC B - */ - for (i = 0; i < 3; i++) { - /* - * The following 2 statements are together endianess - * independent. Remember this when changing. - */ - SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); - - XM_OUT16(IoC, Port, (XM_SA + i * 2), SWord); - } - - /* Tx Inter Packet Gap (XM_TX_IPG): use default */ - /* Tx High Water Mark (XM_TX_HI_WM): use default */ - /* Tx Low Water Mark (XM_TX_LO_WM): use default */ - /* Host Request Threshold (XM_HT_THR): use default */ - /* Rx Request Threshold (XM_RX_THR): use default */ - /* Rx Low Water Mark (XM_RX_LO_WM): use default */ - - /* configure Rx High Water Mark (XM_RX_HI_WM) */ - XM_OUT16(IoC, Port, XM_RX_HI_WM, SK_XM_RX_HI_WM); - - /* Configure Tx Request Threshold */ - SWord = SK_XM_THR_SL; /* for single port */ - - if (pAC->GIni.GIMacsFound > 1) { - switch (pAC->GIni.GIPortUsage) { - case SK_RED_LINK: - SWord = SK_XM_THR_REDL; /* redundant link */ - break; - case SK_MUL_LINK: - SWord = SK_XM_THR_MULL; /* load balancing */ - break; - case SK_JUMBO_LINK: - SWord = SK_XM_THR_JUMBO; /* jumbo frames */ - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E014, SKERR_HWI_E014MSG); - break; - } - } - XM_OUT16(IoC, Port, XM_TX_THR, SWord); - - /* setup register defaults for the Tx Command Register */ - XM_OUT16(IoC, Port, XM_TX_CMD, XM_TX_AUTO_PAD); - - /* setup register defaults for the Rx Command Register */ - SWord = XM_RX_STRIP_FCS | XM_RX_LENERR_OK; - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - SWord |= XM_RX_BIG_PK_OK; - } - - if (pPrt->PLinkMode == SK_LMODE_HALF) { - /* - * If in manual half duplex mode the other side might be in - * full duplex mode, so ignore if a carrier extension is not seen - * on frames received - */ - SWord |= XM_RX_DIS_CEXT; - } - - XM_OUT16(IoC, Port, XM_RX_CMD, SWord); - - /* - * setup register defaults for the Mode Register - * - Don't strip error frames to avoid Store & Forward - * on the Rx side. - * - Enable 'Check Station Address' bit - * - Enable 'Check Address Array' bit - */ - XM_OUT32(IoC, Port, XM_MODE, XM_DEF_MODE); - - /* - * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) - * - Enable all bits excepting 'Octets Rx OK Low CntOv' - * and 'Octets Rx OK Hi Cnt Ov'. - */ - XM_OUT32(IoC, Port, XM_RX_EV_MSK, XMR_DEF_MSK); - - /* - * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) - * - Enable all bits excepting 'Octets Tx OK Low CntOv' - * and 'Octets Tx OK Hi Cnt Ov'. - */ - XM_OUT32(IoC, Port, XM_TX_EV_MSK, XMT_DEF_MSK); - - /* - * Do NOT init XMAC interrupt mask here. - * All interrupts remain disable until link comes up! - */ - - /* - * Any additional configuration changes may be done now. - * The last action is to enable the Rx and Tx state machine. - * This should be done after the auto-negotiation process - * has been completed successfully. - */ -} /* SkXmInitMac */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmInitMac() - Initialize the GMAC - * - * Description: - * Initialize the GMAC of the specified port. - * The GMAC must be reset or stopped before calling this function. - * - * Note: - * The GMAC's Rx and Tx state machine is still disabled when returning. - * - * Returns: - * nothing - */ -void SkGmInitMac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int i; - SK_U16 SWord; - SK_U32 DWord; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PState == SK_PRT_STOP) { - /* Port State: SK_PRT_STOP */ - /* Verify that the reset bit is cleared */ - SK_IN32(IoC, MR_ADDR(Port, GMAC_CTRL), &DWord); - - if ((DWord & GMC_RST_SET) != 0) { - /* PState does not match HW state */ - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E006, SKERR_HWI_E006MSG); - /* Correct it */ - pPrt->PState = SK_PRT_RESET; - } - } - - if (pPrt->PState == SK_PRT_RESET) { - - SkGmHardRst(pAC, IoC, Port); - - SkGmClearRst(pAC, IoC, Port); - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - /* Auto-negotiation disabled */ - - /* get General Purpose Control */ - GM_IN16(IoC, Port, GM_GP_CTRL, &SWord); - - /* disable auto-update for speed, duplex and flow-control */ - SWord |= GM_GPCR_AU_ALL_DIS; - - /* setup General Purpose Control Register */ - GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); - - SWord = GM_GPCR_AU_ALL_DIS; - } - else { - SWord = 0; - } - - /* speed settings */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - case SK_LSPEED_1000MBPS: - SWord |= GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100; - break; - case SK_LSPEED_100MBPS: - SWord |= GM_GPCR_SPEED_100; - break; - case SK_LSPEED_10MBPS: - break; - } - - /* duplex settings */ - if (pPrt->PLinkMode != SK_LMODE_HALF) { - /* set full duplex */ - SWord |= GM_GPCR_DUP_FULL; - } - - /* flow-control settings */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - /* set Pause Off */ - SK_OUT32(IoC, MR_ADDR(Port, GMAC_CTRL), GMC_PAUSE_OFF); - /* disable Tx & Rx flow-control */ - SWord |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; - break; - case SK_FLOW_MODE_LOC_SEND: - /* disable Rx flow-control */ - SWord |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; - break; - case SK_FLOW_MODE_SYMMETRIC: - case SK_FLOW_MODE_SYM_OR_REM: - /* enable Tx & Rx flow-control */ - break; - } - - /* setup General Purpose Control Register */ - GM_OUT16(IoC, Port, GM_GP_CTRL, SWord); - - /* dummy read the Interrupt Source Register */ - SK_IN16(IoC, GMAC_IRQ_SRC, &SWord); - -#ifndef VCPU - /* read Id from PHY */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_ID1, &pPrt->PhyId1); - - SkGmInitPhyMarv(pAC, IoC, Port, SK_FALSE); -#endif /* VCPU */ - } - - (void)SkGmResetCounter(pAC, IoC, Port); - - /* setup Transmit Control Register */ - GM_OUT16(IoC, Port, GM_TX_CTRL, TX_COL_THR(pPrt->PMacColThres)); - - /* setup Receive Control Register */ - GM_OUT16(IoC, Port, GM_RX_CTRL, GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA | - GM_RXCR_CRC_DIS); - - /* setup Transmit Flow Control Register */ - GM_OUT16(IoC, Port, GM_TX_FLOW_CTRL, 0xffff); - - /* setup Transmit Parameter Register */ -#ifdef VCPU - GM_IN16(IoC, Port, GM_TX_PARAM, &SWord); -#endif /* VCPU */ - - SWord = TX_JAM_LEN_VAL(pPrt->PMacJamLen) | - TX_JAM_IPG_VAL(pPrt->PMacJamIpgVal) | - TX_IPG_JAM_DATA(pPrt->PMacJamIpgData); - - GM_OUT16(IoC, Port, GM_TX_PARAM, SWord); - - /* configure the Serial Mode Register */ -#ifdef VCPU - GM_IN16(IoC, Port, GM_SERIAL_MODE, &SWord); -#endif /* VCPU */ - - SWord = GM_SMOD_VLAN_ENA | IPG_DATA_VAL(pPrt->PMacIpgData); - - if (pPrt->PMacLimit4) { - /* reset of collision counter after 4 consecutive collisions */ - SWord |= GM_SMOD_LIMIT_4; - } - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - /* enable jumbo mode (Max. Frame Length = 9018) */ - SWord |= GM_SMOD_JUMBO_ENA; - } - - GM_OUT16(IoC, Port, GM_SERIAL_MODE, SWord); - - /* - * configure the GMACs Station Addresses - * in PROM you can find our addresses at: - * B2_MAC_1 = xx xx xx xx xx x0 virtual address - * B2_MAC_2 = xx xx xx xx xx x1 is programmed to GMAC A - * B2_MAC_3 = xx xx xx xx xx x2 is reserved for DualPort - */ - - for (i = 0; i < 3; i++) { - /* - * The following 2 statements are together endianess - * independent. Remember this when changing. - */ - /* physical address: will be used for pause frames */ - SK_IN16(IoC, (B2_MAC_2 + Port * 8 + i * 2), &SWord); - -#ifdef WA_DEV_16 - /* WA for deviation #16 */ - if (pAC->GIni.GIChipId == CHIP_ID_YUKON && pAC->GIni.GIChipRev == 0) { - /* swap the address bytes */ - SWord = ((SWord & 0xff00) >> 8) | ((SWord & 0x00ff) << 8); - - /* write to register in reversed order */ - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + (2 - i) * 4), SWord); - } - else { - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); - } -#else - GM_OUT16(IoC, Port, (GM_SRC_ADDR_1L + i * 4), SWord); -#endif /* WA_DEV_16 */ - - /* virtual address: will be used for data */ - SK_IN16(IoC, (B2_MAC_1 + Port * 8 + i * 2), &SWord); - - GM_OUT16(IoC, Port, (GM_SRC_ADDR_2L + i * 4), SWord); - - /* reset Multicast filtering Hash registers 1-3 */ - GM_OUT16(IoC, Port, GM_MC_ADDR_H1 + 4*i, 0); - } - - /* reset Multicast filtering Hash register 4 */ - GM_OUT16(IoC, Port, GM_MC_ADDR_H4, 0); - - /* enable interrupt mask for counter overflows */ - GM_OUT16(IoC, Port, GM_TX_IRQ_MSK, 0); - GM_OUT16(IoC, Port, GM_RX_IRQ_MSK, 0); - GM_OUT16(IoC, Port, GM_TR_IRQ_MSK, 0); - -#if defined(SK_DIAG) || defined(DEBUG) - /* read General Purpose Status */ - GM_IN16(IoC, Port, GM_GP_STAT, &SWord); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("MAC Stat Reg.=0x%04X\n", SWord)); -#endif /* SK_DIAG || DEBUG */ - -#ifdef SK_DIAG - c_print("MAC Stat Reg=0x%04X\n", SWord); -#endif /* SK_DIAG */ - -} /* SkGmInitMac */ -#endif /* YUKON */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmInitDupMd() - Initialize the XMACs Duplex Mode - * - * Description: - * This function initializes the XMACs Duplex Mode. - * It should be called after successfully finishing - * the Auto-negotiation Process - * - * Returns: - * nothing - */ -static void SkXmInitDupMd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - switch (pAC->GIni.GP[Port].PLinkModeStatus) { - case SK_LMODE_STAT_AUTOHALF: - case SK_LMODE_STAT_HALF: - /* Configuration Actions for Half Duplex Mode */ - /* - * XM_BURST = default value. We are probable not quick - * enough at the 'XMAC' bus to burst 8kB. - * The XMAC stops bursting if no transmit frames - * are available or the burst limit is exceeded. - */ - /* XM_TX_RT_LIM = default value (15) */ - /* XM_TX_STIME = default value (0xff = 4096 bit times) */ - break; - case SK_LMODE_STAT_AUTOFULL: - case SK_LMODE_STAT_FULL: - /* Configuration Actions for Full Duplex Mode */ - /* - * The duplex mode is configured by the PHY, - * therefore it seems to be that there is nothing - * to do here. - */ - break; - case SK_LMODE_STAT_UNKNOWN: - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E007, SKERR_HWI_E007MSG); - break; - } -} /* SkXmInitDupMd */ - - -/****************************************************************************** - * - * SkXmInitPauseMd() - initialize the Pause Mode to be used for this port - * - * Description: - * This function initializes the Pause Mode which should - * be used for this port. - * It should be called after successfully finishing - * the Auto-negotiation Process - * - * Returns: - * nothing - */ -static void SkXmInitPauseMd( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U32 DWord; - SK_U16 Word; - - pPrt = &pAC->GIni.GP[Port]; - - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - - if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_NONE || - pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { - - /* Disable Pause Frame Reception */ - Word |= XM_MMU_IGN_PF; - } - else { - /* - * enabling pause frame reception is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - /* Enable Pause Frame Reception */ - Word &= ~XM_MMU_IGN_PF; - } - - XM_OUT16(IoC, Port, XM_MMU_CMD, Word); - - XM_IN32(IoC, Port, XM_MODE, &DWord); - - if (pPrt->PFlowCtrlStatus == SK_FLOW_STAT_SYMMETRIC || - pPrt->PFlowCtrlStatus == SK_FLOW_STAT_LOC_SEND) { - - /* - * Configure Pause Frame Generation - * Use internal and external Pause Frame Generation. - * Sending pause frames is edge triggered. - * Send a Pause frame with the maximum pause time if - * internal oder external FIFO full condition occurs. - * Send a zero pause time frame to re-start transmission. - */ - - /* XM_PAUSE_DA = '010000C28001' (default) */ - - /* XM_MAC_PTIME = 0xffff (maximum) */ - /* remember this value is defined in big endian (!) */ - XM_OUT16(IoC, Port, XM_MAC_PTIME, 0xffff); - - /* Set Pause Mode in Mode Register */ - DWord |= XM_PAUSE_MODE; - - /* Set Pause Mode in MAC Rx FIFO */ - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_ENA_PAUSE); - } - else { - /* - * disable pause frame generation is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - /* Disable Pause Mode in Mode Register */ - DWord &= ~XM_PAUSE_MODE; - - /* Disable Pause Mode in MAC Rx FIFO */ - SK_OUT16(IoC, MR_ADDR(Port, RX_MFF_CTRL1), MFF_DIS_PAUSE); - } - - XM_OUT32(IoC, Port, XM_MODE, DWord); -} /* SkXmInitPauseMd*/ - - -/****************************************************************************** - * - * SkXmInitPhyXmac() - Initialize the XMAC Phy registers - * - * Description: initializes all the XMACs Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl; - - pPrt = &pAC->GIni.GP[Port]; - Ctrl = 0; - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyXmac: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - Ctrl |= PHY_CT_DUP_MD; - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLEs are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyXmac: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl |= PHY_X_AN_HD; - break; - case SK_LMODE_AUTOFULL: - Ctrl |= PHY_X_AN_FD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl |= PHY_X_AN_FD | PHY_X_AN_HD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl |= PHY_X_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl |= PHY_X_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl |= PHY_X_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl |= PHY_X_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_AUNE_ADV, Ctrl); - - /* Restart Auto-negotiation */ - Ctrl = PHY_CT_ANE | PHY_CT_RE_CFG; - } - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl |= PHY_CT_LOOP; - } - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_XMAC_CTRL, Ctrl); -} /* SkXmInitPhyXmac */ - - -/****************************************************************************** - * - * SkXmInitPhyBcom() - Initialize the Broadcom Phy registers - * - * Description: initializes all the Broadcom Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyBcom( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl1; - SK_U16 Ctrl2; - SK_U16 Ctrl3; - SK_U16 Ctrl4; - SK_U16 Ctrl5; - - Ctrl1 = PHY_CT_SP1000; - Ctrl2 = 0; - Ctrl3 = PHY_SEL_TYPE; - Ctrl4 = PHY_B_PEC_EN_LTR; - Ctrl5 = PHY_B_AC_TX_TST; - - pPrt = &pAC->GIni.GP[Port]; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_B_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - Ctrl2 |= PHY_B_1000C_MSC; - } - } - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyBcom: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - Ctrl1 |= PHY_CT_DUP_MD; - } - - /* Determine Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_B_1000C_MSE; /* set it to Slave */ - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyBcom: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* - * Workaround BCOM Errata #1 for the C5 type. - * 1000Base-T Link Acquisition Failure in Slave Mode - * Set Repeater/DTE bit 10 of the 1000Base-T Control Register - */ - Ctrl2 |= PHY_B_1000C_RD; - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl2 |= PHY_B_1000C_AHD; - break; - case SK_LMODE_AUTOFULL: - Ctrl2 |= PHY_B_1000C_AFD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl2 |= PHY_B_1000C_AFD | PHY_B_1000C_AHD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl3 |= PHY_B_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl3 |= PHY_B_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl3 |= PHY_B_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl3 |= PHY_B_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Restart Auto-negotiation */ - Ctrl1 |= PHY_CT_ANE | PHY_CT_RE_CFG; - } - - /* Initialize LED register here? */ - /* No. Please do it in SkDgXmitLed() (if required) and swap - init order of LEDs and XMAC. (MAl) */ - - /* Write 1000Base-T Control Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_1000T_CTRL, Ctrl2); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set 1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUNE_ADV, Ctrl3); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3)); - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl1 |= PHY_CT_LOOP; - } - - if (pAC->GIni.GIPortUsage == SK_JUMBO_LINK) { - /* configure FIFO to high latency for transmission of ext. packets */ - Ctrl4 |= PHY_B_PEC_HIGH_LA; - - /* configure reception of extended packets */ - Ctrl5 |= PHY_B_AC_LONG_PACK; - - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, Ctrl5); - } - - /* Configure LED Traffic Mode and Jumbo Frame usage if specified */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_P_EXT_CTRL, Ctrl4); - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_CTRL, Ctrl1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Control Reg=0x%04X\n", Ctrl1)); -} /* SkXmInitPhyBcom */ -#endif /* GENESIS */ - -#ifdef YUKON -/****************************************************************************** - * - * SkGmInitPhyMarv() - Initialize the Marvell Phy registers - * - * Description: initializes all the Marvell Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkGmInitPhyMarv( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 PhyCtrl; - SK_U16 C1000BaseT; - SK_U16 AutoNegAdv; - SK_U16 ExtPhyCtrl; - SK_U16 LedCtrl; - SK_BOOL AutoNeg; -#if defined(SK_DIAG) || defined(DEBUG) - SK_U16 PhyStat; - SK_U16 PhyStat1; - SK_U16 PhySpecStat; -#endif /* SK_DIAG || DEBUG */ - - pPrt = &pAC->GIni.GP[Port]; - - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - AutoNeg = SK_FALSE; - } - else { - AutoNeg = SK_TRUE; - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyMarv: Port %d, auto-negotiation %s\n", - Port, AutoNeg ? "ON" : "OFF")); - -#ifdef VCPU - VCPUprintf(0, "SkGmInitPhyMarv(), Port=%u, DoLoop=%u\n", - Port, DoLoop); -#else /* VCPU */ - if (DoLoop) { - /* Set 'MAC Power up'-bit, set Manual MDI configuration */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, - PHY_M_PC_MAC_POW_UP); - } - else if (AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_AUTO) { - /* Read Ext. PHY Specific Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); - - ExtPhyCtrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | - PHY_M_EC_MAC_S_MSK); - - ExtPhyCtrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ) | - PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, ExtPhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl)); - } - - /* Read PHY Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); - - if (!AutoNeg) { - /* Disable Auto-negotiation */ - PhyCtrl &= ~PHY_CT_ANE; - } - - PhyCtrl |= PHY_CT_RESET; - /* Assert software reset */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); -#endif /* VCPU */ - - PhyCtrl = 0 /* PHY_CT_COL_TST */; - C1000BaseT = 0; - AutoNegAdv = PHY_SEL_TYPE; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - /* enable Manual Master/Slave */ - C1000BaseT |= PHY_M_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - C1000BaseT |= PHY_M_1000C_MSC; /* set it to Master */ - } - } - - /* Auto-negotiation ? */ - if (!AutoNeg) { - - if (pPrt->PLinkMode == SK_LMODE_FULL) { - /* Set Full Duplex Mode */ - PhyCtrl |= PHY_CT_DUP_MD; - } - - /* Set Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - C1000BaseT |= PHY_M_1000C_MSE; /* set it to Slave */ - } - - /* Set Speed */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - case SK_LSPEED_1000MBPS: - PhyCtrl |= PHY_CT_SP1000; - break; - case SK_LSPEED_100MBPS: - PhyCtrl |= PHY_CT_SP100; - break; - case SK_LSPEED_10MBPS: - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, - SKERR_HWI_E019MSG); - } - - if (!DoLoop) { - PhyCtrl |= PHY_CT_RESET; - } - } - else { - /* Set Auto-negotiation advertisement */ - - if (pAC->GIni.GICopperType) { - /* Set Speed capabilities */ - switch (pPrt->PLinkSpeed) { - case SK_LSPEED_AUTO: - C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; - AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | - PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - case SK_LSPEED_1000MBPS: - C1000BaseT |= PHY_M_1000C_AHD | PHY_M_1000C_AFD; - break; - case SK_LSPEED_100MBPS: - AutoNegAdv |= PHY_M_AN_100_FD | PHY_M_AN_100_HD | - /* advertise 10Base-T also */ - PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - case SK_LSPEED_10MBPS: - AutoNegAdv |= PHY_M_AN_10_FD | PHY_M_AN_10_HD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E019, - SKERR_HWI_E019MSG); - } - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - C1000BaseT &= ~PHY_M_1000C_AFD; - AutoNegAdv &= ~(PHY_M_AN_100_FD | PHY_M_AN_10_FD); - break; - case SK_LMODE_AUTOFULL: - C1000BaseT &= ~PHY_M_1000C_AHD; - AutoNegAdv &= ~(PHY_M_AN_100_HD | PHY_M_AN_10_HD); - break; - case SK_LMODE_AUTOBOTH: - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - AutoNegAdv |= PHY_B_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - AutoNegAdv |= PHY_B_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - AutoNegAdv |= PHY_B_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - AutoNegAdv |= PHY_B_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - } - else { /* special defines for FIBER (88E1011S only) */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - AutoNegAdv |= PHY_M_AN_1000X_AHD; - break; - case SK_LMODE_AUTOFULL: - AutoNegAdv |= PHY_M_AN_1000X_AFD; - break; - case SK_LMODE_AUTOBOTH: - AutoNegAdv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - AutoNegAdv |= PHY_M_P_NO_PAUSE_X; - break; - case SK_FLOW_MODE_LOC_SEND: - AutoNegAdv |= PHY_M_P_ASYM_MD_X; - break; - case SK_FLOW_MODE_SYMMETRIC: - AutoNegAdv |= PHY_M_P_SYM_MD_X; - break; - case SK_FLOW_MODE_SYM_OR_REM: - AutoNegAdv |= PHY_M_P_BOTH_MD_X; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - } - - if (!DoLoop) { - /* Restart Auto-negotiation */ - PhyCtrl |= PHY_CT_ANE | PHY_CT_RE_CFG; - } - } - -#ifdef VCPU - /* - * E-mail from Gu Lin (08-03-2002): - */ - - /* Program PHY register 30 as 16'h0708 for simulation speed up */ - SkGmPhyWrite(pAC, IoC, Port, 30, 0x0700 /* 0x0708 */); - - VCpuWait(2000); - -#else /* VCPU */ - - /* Write 1000Base-T Control Register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_1000T_CTRL, C1000BaseT); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set 1000B-T Ctrl =0x%04X\n", C1000BaseT)); - - /* Write AutoNeg Advertisement Register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_AUNE_ADV, AutoNegAdv); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set Auto-Neg.Adv.=0x%04X\n", AutoNegAdv)); -#endif /* VCPU */ - - if (DoLoop) { - /* Set the PHY Loopback bit */ - PhyCtrl |= PHY_CT_LOOP; - -#ifdef XXX - /* Program PHY register 16 as 16'h0400 to force link good */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, PHY_M_PC_FL_GOOD); -#endif /* XXX */ - -#ifndef VCPU - if (pPrt->PLinkSpeed != SK_LSPEED_AUTO) { - /* Write Ext. PHY Specific Control */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_CTRL, - (SK_U16)((pPrt->PLinkSpeed + 2) << 4)); - } -#endif /* VCPU */ - } -#ifdef TEST_ONLY - else if (pPrt->PLinkSpeed == SK_LSPEED_10MBPS) { - /* Write PHY Specific Control */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_PHY_CTRL, - PHY_M_PC_EN_DET_MSK); - } -#endif - - /* Write to the PHY Control register */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CTRL, PhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Set PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); - -#ifdef VCPU - VCpuWait(2000); -#else - - LedCtrl = PHY_M_LED_PULS_DUR(PULS_170MS) | PHY_M_LED_BLINK_RT(BLINK_84MS); - - if ((pAC->GIni.GILedBlinkCtrl & SK_ACT_LED_BLINK) != 0) { - LedCtrl |= PHY_M_LEDC_RX_CTRL | PHY_M_LEDC_TX_CTRL; - } - - if ((pAC->GIni.GILedBlinkCtrl & SK_DUP_LED_NORMAL) != 0) { - LedCtrl |= PHY_M_LEDC_DP_CTRL; - } - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_CTRL, LedCtrl); - - if ((pAC->GIni.GILedBlinkCtrl & SK_LED_LINK100_ON) != 0) { - /* only in forced 100 Mbps mode */ - if (!AutoNeg && pPrt->PLinkSpeed == SK_LSPEED_100MBPS) { - - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_100(MO_LED_ON)); - } - } - -#ifdef SK_DIAG - c_print("Set PHY Ctrl=0x%04X\n", PhyCtrl); - c_print("Set 1000 B-T=0x%04X\n", C1000BaseT); - c_print("Set Auto-Neg=0x%04X\n", AutoNegAdv); - c_print("Set Ext Ctrl=0x%04X\n", ExtPhyCtrl); -#endif /* SK_DIAG */ - -#if defined(SK_DIAG) || defined(DEBUG) - /* Read PHY Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CTRL, &PhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Ctrl Reg.=0x%04X\n", PhyCtrl)); - - /* Read 1000Base-T Control Register */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_CTRL, &C1000BaseT); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl =0x%04X\n", C1000BaseT)); - - /* Read AutoNeg Advertisement Register */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_ADV, &AutoNegAdv); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg.Adv.=0x%04X\n", AutoNegAdv)); - - /* Read Ext. PHY Specific Control */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_EXT_CTRL, &ExtPhyCtrl); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Ext. PHY Ctrl=0x%04X\n", ExtPhyCtrl)); - - /* Read PHY Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Stat Reg.=0x%04X\n", PhyStat)); - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_STAT, &PhyStat1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Stat Reg.=0x%04X\n", PhyStat1)); - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &PhySpecStat); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Spec Stat=0x%04X\n", PhySpecStat)); -#endif /* SK_DIAG || DEBUG */ - -#ifdef SK_DIAG - c_print("PHY Ctrl Reg=0x%04X\n", PhyCtrl); - c_print("PHY 1000 Reg=0x%04X\n", C1000BaseT); - c_print("PHY AnAd Reg=0x%04X\n", AutoNegAdv); - c_print("Ext Ctrl Reg=0x%04X\n", ExtPhyCtrl); - c_print("PHY Stat Reg=0x%04X\n", PhyStat); - c_print("PHY Stat Reg=0x%04X\n", PhyStat1); - c_print("PHY Spec Reg=0x%04X\n", PhySpecStat); -#endif /* SK_DIAG */ - -#endif /* VCPU */ - -} /* SkGmInitPhyMarv */ -#endif /* YUKON */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkXmInitPhyLone() - Initialize the Level One Phy registers - * - * Description: initializes all the Level One Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyLone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - SK_U16 Ctrl1; - SK_U16 Ctrl2; - SK_U16 Ctrl3; - - Ctrl1 = PHY_CT_SP1000; - Ctrl2 = 0; - Ctrl3 = PHY_SEL_TYPE; - - pPrt = &pAC->GIni.GP[Port]; - - /* manually Master/Slave ? */ - if (pPrt->PMSMode != SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_L_1000C_MSE; - - if (pPrt->PMSMode == SK_MS_MODE_MASTER) { - Ctrl2 |= PHY_L_1000C_MSC; - } - } - /* Auto-negotiation ? */ - if (pPrt->PLinkMode == SK_LMODE_HALF || pPrt->PLinkMode == SK_LMODE_FULL) { - /* - * level one spec say: "1000 Mbps: manual mode not allowed" - * but lets see what happens... - */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyLone: no auto-negotiation Port %d\n", Port)); - /* Set DuplexMode in Config register */ - if (pPrt->PLinkMode == SK_LMODE_FULL) { - Ctrl1 |= PHY_CT_DUP_MD; - } - - /* Determine Master/Slave manually if not already done */ - if (pPrt->PMSMode == SK_MS_MODE_AUTO) { - Ctrl2 |= PHY_L_1000C_MSE; /* set it to Slave */ - } - - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLES are transmitted - */ - } - else { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("InitPhyLone: with auto-negotiation Port %d\n", Port)); - /* Set Auto-negotiation advertisement */ - - /* Set Full/half duplex capabilities */ - switch (pPrt->PLinkMode) { - case SK_LMODE_AUTOHALF: - Ctrl2 |= PHY_L_1000C_AHD; - break; - case SK_LMODE_AUTOFULL: - Ctrl2 |= PHY_L_1000C_AFD; - break; - case SK_LMODE_AUTOBOTH: - Ctrl2 |= PHY_L_1000C_AFD | PHY_L_1000C_AHD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E015, - SKERR_HWI_E015MSG); - } - - /* Set Flow-control capabilities */ - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - Ctrl3 |= PHY_L_P_NO_PAUSE; - break; - case SK_FLOW_MODE_LOC_SEND: - Ctrl3 |= PHY_L_P_ASYM_MD; - break; - case SK_FLOW_MODE_SYMMETRIC: - Ctrl3 |= PHY_L_P_SYM_MD; - break; - case SK_FLOW_MODE_SYM_OR_REM: - Ctrl3 |= PHY_L_P_BOTH_MD; - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - /* Restart Auto-negotiation */ - Ctrl1 = PHY_CT_ANE | PHY_CT_RE_CFG; - } - - /* Write 1000Base-T Control Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_1000T_CTRL, Ctrl2); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("1000B-T Ctrl Reg=0x%04X\n", Ctrl2)); - - /* Write AutoNeg Advertisement Register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_AUNE_ADV, Ctrl3); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Auto-Neg.Adv.Reg=0x%04X\n", Ctrl3)); - - if (DoLoop) { - /* Set the Phy Loopback bit, too */ - Ctrl1 |= PHY_CT_LOOP; - } - - /* Write to the Phy control register */ - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_CTRL, Ctrl1); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Control Reg=0x%04X\n", Ctrl1)); -} /* SkXmInitPhyLone */ - - -/****************************************************************************** - * - * SkXmInitPhyNat() - Initialize the National Phy registers - * - * Description: initializes all the National Phy registers - * - * Note: - * - * Returns: - * nothing - */ -static void SkXmInitPhyNat( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ -/* todo: National */ -} /* SkXmInitPhyNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkMacInitPhy() - Initialize the PHY registers - * - * Description: calls the Init PHY routines dep. on board type - * - * Note: - * - * Returns: - * nothing - */ -void SkMacInitPhy( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL DoLoop) /* Should a Phy LoopBack be set-up? */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - switch (pPrt->PhyType) { - case SK_PHY_XMAC: - SkXmInitPhyXmac(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_BCOM: - SkXmInitPhyBcom(pAC, IoC, Port, DoLoop); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmInitPhyLone(pAC, IoC, Port, DoLoop); - break; - case SK_PHY_NAT: - SkXmInitPhyNat(pAC, IoC, Port, DoLoop); - break; -#endif /* OTHER_PHY */ - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - SkGmInitPhyMarv(pAC, IoC, Port, DoLoop); - } -#endif /* YUKON */ - -} /* SkMacInitPhy */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmAutoNegDoneXmac() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 LPAb; /* Link Partner Ability */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneXmac, Port %d\n", Port)); - - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_AUNE_LP, &LPAb); - SkXmPhyRead(pAC, IoC, Port, PHY_XMAC_RES_ABI, &ResAb); - - if ((LPAb & PHY_X_AN_RFB) != 0) { - /* At least one of the remote fault bit is set */ - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_FD) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; - } - else if ((ResAb & (PHY_X_RS_HD | PHY_X_RS_FD)) == PHY_X_RS_HD) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; - } - else { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_DUP_CAP); - } - - /* Check PAUSE mismatch */ - /* We are NOT using chapter 4.23 of the Xaqti manual */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYMMETRIC || - pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM) && - (LPAb & PHY_X_P_SYM_MD) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_SYM_OR_REM && - (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if (pPrt->PFlowCtrlMode == SK_FLOW_MODE_LOC_SEND && - (LPAb & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; - - return(SK_AND_OK); -} /* SkXmAutoNegDoneXmac */ - - -/****************************************************************************** - * - * SkXmAutoNegDoneBcom() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneBcom( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 AuxStat; /* Auxiliary Status */ - -#ifdef TEST_ONLY -01-Sep-2000 RA;:;: - SK_U16 ResAb; /* Resolved Ability */ -#endif /* 0 */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneBcom, Port %d\n", Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUNE_LP, &LPAb); -#ifdef TEST_ONLY -01-Sep-2000 RA;:;: - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_1000T_STAT, &ResAb); -#endif /* 0 */ - - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_STAT, &AuxStat); - - if ((LPAb & PHY_B_AN_RF) != 0) { - /* Remote fault bit is set: Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000FD) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; - } - else if ((AuxStat & PHY_B_AS_AN_RES_MSK) == PHY_B_RES_1000HD) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; - } - else { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Duplex mode mismatch Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_DUP_CAP); - } - -#ifdef TEST_ONLY -01-Sep-2000 RA;:;: - /* Check Master/Slave resolution */ - if ((ResAb & PHY_B_1000S_MSF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - SK_MS_STAT_MASTER : SK_MS_STAT_SLAVE; -#endif /* 0 */ - - /* Check PAUSE mismatch ??? */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PAUSE_MSK) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRR) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((AuxStat & PHY_B_AS_PAUSE_MSK) == PHY_B_AS_PRT) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; - - return(SK_AND_OK); -} /* SkXmAutoNegDoneBcom */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmAutoNegDoneMarv() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkGmAutoNegDoneMarv( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 AuxStat; /* Auxiliary Status */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneMarv, Port %d\n", Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_AUNE_LP, &LPAb); - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Link P.Abil.=0x%04X\n", LPAb)); - - if ((LPAb & PHY_M_AN_RF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_1000T_STAT, &ResAb); - - /* Check Master/Slave resolution */ - if ((ResAb & PHY_B_1000S_MSF) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - - pPrt->PMSStatus = ((ResAb & PHY_B_1000S_MSR) != 0) ? - (SK_U8)SK_MS_STAT_MASTER : (SK_U8)SK_MS_STAT_SLAVE; - - /* Read PHY Specific Status */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_PHY_STAT, &AuxStat); - - /* Check Speed & Duplex resolved */ - if ((AuxStat & PHY_M_PS_SPDUP_RES) == 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Speed & Duplex not resolved, Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_UNKNOWN; - return(SK_AND_DUP_CAP); - } - - if ((AuxStat & PHY_M_PS_FULL_DUP) != 0) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; - } - else { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; - } - - /* Check PAUSE mismatch ??? */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_PAUSE_MSK) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_RX_P_EN) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((AuxStat & PHY_M_PS_PAUSE_MSK) == PHY_M_PS_TX_P_EN) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - else { - /* PAUSE mismatch -> no PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - } - - /* set used link speed */ - switch ((unsigned)(AuxStat & PHY_M_PS_SPEED_MSK)) { - case (unsigned)PHY_M_PS_SPEED_1000: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_1000MBPS; - break; - case PHY_M_PS_SPEED_100: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_100MBPS; - break; - default: - pPrt->PLinkSpeedUsed = (SK_U8)SK_LSPEED_STAT_10MBPS; - } - - return(SK_AND_OK); -} /* SkGmAutoNegDoneMarv */ -#endif /* YUKON */ - - -#ifdef OTHER_PHY -/****************************************************************************** - * - * SkXmAutoNegDoneLone() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneLone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 ResAb; /* Resolved Ability */ - SK_U16 LPAb; /* Link Partner Ability */ - SK_U16 QuickStat; /* Auxiliary Status */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegDoneLone, Port %d\n", Port)); - pPrt = &pAC->GIni.GP[Port]; - - /* Get PHY parameters */ - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_AUNE_LP, &LPAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_1000T_STAT, &ResAb); - SkXmPhyRead(pAC, IoC, Port, PHY_LONE_Q_STAT, &QuickStat); - - if ((LPAb & PHY_L_AN_RF) != 0) { - /* Remote fault bit is set */ - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegFail: Remote fault bit set Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - return(SK_AND_OTHER); - } - - /* Check Duplex mismatch */ - if ((QuickStat & PHY_L_QS_DUP_MOD) != 0) { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOFULL; - } - else { - pPrt->PLinkModeStatus = (SK_U8)SK_LMODE_STAT_AUTOHALF; - } - - /* Check Master/Slave resolution */ - if ((ResAb & PHY_L_1000S_MSF) != 0) { - /* Error */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("Master/Slave Fault Port %d\n", Port)); - pPrt->PAutoNegFail = SK_TRUE; - pPrt->PMSStatus = SK_MS_STAT_FAULT; - return(SK_AND_OTHER); - } - else if (ResAb & PHY_L_1000S_MSR) { - pPrt->PMSStatus = SK_MS_STAT_MASTER; - } - else { - pPrt->PMSStatus = SK_MS_STAT_SLAVE; - } - - /* Check PAUSE mismatch */ - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - /* we must manually resolve the abilities here */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_NONE; - - switch (pPrt->PFlowCtrlMode) { - case SK_FLOW_MODE_NONE: - /* default */ - break; - case SK_FLOW_MODE_LOC_SEND: - if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == - (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) { - /* Disable PAUSE receive, enable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_LOC_SEND; - } - break; - case SK_FLOW_MODE_SYMMETRIC: - if ((QuickStat & PHY_L_QS_PAUSE) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - break; - case SK_FLOW_MODE_SYM_OR_REM: - if ((QuickStat & (PHY_L_QS_PAUSE | PHY_L_QS_AS_PAUSE)) == - PHY_L_QS_AS_PAUSE) { - /* Enable PAUSE receive, disable PAUSE transmit */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_REM_SEND; - } - else if ((QuickStat & PHY_L_QS_PAUSE) != 0) { - /* Symmetric PAUSE */ - pPrt->PFlowCtrlStatus = SK_FLOW_STAT_SYMMETRIC; - } - break; - default: - SK_ERR_LOG(pAC, SK_ERRCL_SW | SK_ERRCL_INIT, SKERR_HWI_E016, - SKERR_HWI_E016MSG); - } - - return(SK_AND_OK); -} /* SkXmAutoNegDoneLone */ - - -/****************************************************************************** - * - * SkXmAutoNegDoneNat() - Auto-negotiation handling - * - * Description: - * This function handles the auto-negotiation if the Done bit is set. - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -static int SkXmAutoNegDoneNat( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -/* todo: National */ - return(SK_AND_OK); -} /* SkXmAutoNegDoneNat */ -#endif /* OTHER_PHY */ - - -/****************************************************************************** - * - * SkMacAutoNegDone() - Auto-negotiation handling - * - * Description: calls the auto-negotiation done routines dep. on board type - * - * Returns: - * SK_AND_OK o.k. - * SK_AND_DUP_CAP Duplex capability error happened - * SK_AND_OTHER Other error happened - */ -int SkMacAutoNegDone( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - int Rtv; - - Rtv = SK_AND_OK; - - pPrt = &pAC->GIni.GP[Port]; - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - switch (pPrt->PhyType) { - - case SK_PHY_XMAC: - Rtv = SkXmAutoNegDoneXmac(pAC, IoC, Port); - break; - case SK_PHY_BCOM: - Rtv = SkXmAutoNegDoneBcom(pAC, IoC, Port); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - Rtv = SkXmAutoNegDoneLone(pAC, IoC, Port); - break; - case SK_PHY_NAT: - Rtv = SkXmAutoNegDoneNat(pAC, IoC, Port); - break; -#endif /* OTHER_PHY */ - default: - return(SK_AND_OTHER); - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - Rtv = SkGmAutoNegDoneMarv(pAC, IoC, Port); - } -#endif /* YUKON */ - - if (Rtv != SK_AND_OK) { - return(Rtv); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNeg done Port %d\n", Port)); - - /* We checked everything and may now enable the link */ - pPrt->PAutoNegFail = SK_FALSE; - - SkMacRxTxEnable(pAC, IoC, Port); - - return(SK_AND_OK); -} /* SkMacAutoNegDone */ - - -/****************************************************************************** - * - * SkMacRxTxEnable() - Enable Rx/Tx activity if port is up - * - * Description: enables Rx/Tx dep. on board type - * - * Returns: - * 0 o.k. - * != 0 Error happened - */ -int SkMacRxTxEnable( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 Reg; /* 16-bit register value */ - SK_U16 IntMask; /* MAC interrupt mask */ -#ifdef GENESIS - SK_U16 SWord; -#endif - - pPrt = &pAC->GIni.GP[Port]; - - if (!pPrt->PHWLinkUp) { - /* The Hardware link is NOT up */ - return(0); - } - - if ((pPrt->PLinkMode == SK_LMODE_AUTOHALF || - pPrt->PLinkMode == SK_LMODE_AUTOFULL || - pPrt->PLinkMode == SK_LMODE_AUTOBOTH) && - pPrt->PAutoNegFail) { - /* Auto-negotiation is not done or failed */ - return(0); - } - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* set Duplex Mode and Pause Mode */ - SkXmInitDupMd(pAC, IoC, Port); - - SkXmInitPauseMd(pAC, IoC, Port); - - /* - * Initialize the Interrupt Mask Register. Default IRQs are... - * - Link Asynchronous Event - * - Link Partner requests config - * - Auto Negotiation Done - * - Rx Counter Event Overflow - * - Tx Counter Event Overflow - * - Transmit FIFO Underrun - */ - IntMask = XM_DEF_MSK; - -#ifdef DEBUG - /* add IRQ for Receive FIFO Overflow */ - IntMask &= ~XM_IS_RXF_OV; -#endif /* DEBUG */ - - if (pPrt->PhyType != SK_PHY_XMAC) { - /* disable GP0 interrupt bit */ - IntMask |= XM_IS_INP_ASS; - } - XM_OUT16(IoC, Port, XM_IMSK, IntMask); - - /* get MMU Command Reg. */ - XM_IN16(IoC, Port, XM_MMU_CMD, &Reg); - - if (pPrt->PhyType != SK_PHY_XMAC && - (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL)) { - /* set to Full Duplex */ - Reg |= XM_MMU_GMII_FD; - } - - switch (pPrt->PhyType) { - case SK_PHY_BCOM: - /* - * Workaround BCOM Errata (#10523) for all BCom Phys - * Enable Power Management after link up - */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &SWord); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(SWord & ~PHY_B_AC_DIS_PM)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, - (SK_U16)PHY_B_DEF_MSK); - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, PHY_L_DEF_MSK); - break; - case SK_PHY_NAT: - /* todo National: - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, PHY_N_DEF_MSK); */ - /* no interrupts possible from National ??? */ - break; -#endif /* OTHER_PHY */ - } - - /* enable Rx/Tx */ - XM_OUT16(IoC, Port, XM_MMU_CMD, Reg | XM_MMU_ENA_RX | XM_MMU_ENA_TX); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* - * Initialize the Interrupt Mask Register. Default IRQs are... - * - Rx Counter Event Overflow - * - Tx Counter Event Overflow - * - Transmit FIFO Underrun - */ - IntMask = GMAC_DEF_MSK; - -#ifdef DEBUG - /* add IRQ for Receive FIFO Overrun */ - IntMask |= GM_IS_RX_FF_OR; -#endif /* DEBUG */ - - SK_OUT8(IoC, GMAC_IRQ_MSK, (SK_U8)IntMask); - - /* get General Purpose Control */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Reg); - - if (pPrt->PLinkModeStatus == SK_LMODE_STAT_FULL || - pPrt->PLinkModeStatus == SK_LMODE_STAT_AUTOFULL) { - /* set to Full Duplex */ - Reg |= GM_GPCR_DUP_FULL; - } - - /* enable Rx/Tx */ - GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Reg | GM_GPCR_RX_ENA | - GM_GPCR_TX_ENA)); - -#ifndef VCPU - /* Enable all PHY interrupts */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, - (SK_U16)PHY_M_DEF_MSK); -#endif /* VCPU */ - } -#endif /* YUKON */ - - return(0); - -} /* SkMacRxTxEnable */ - - -/****************************************************************************** - * - * SkMacRxTxDisable() - Disable Receiver and Transmitter - * - * Description: disables Rx/Tx dep. on board type - * - * Returns: N/A - */ -void SkMacRxTxDisable( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Word; - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - - XM_OUT16(IoC, Port, XM_MMU_CMD, Word & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); - - /* dummy read to ensure writing */ - XM_IN16(IoC, Port, XM_MMU_CMD, &Word); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - - GM_IN16(IoC, Port, GM_GP_CTRL, &Word); - - GM_OUT16(IoC, Port, GM_GP_CTRL, (SK_U16)(Word & ~(GM_GPCR_RX_ENA | - GM_GPCR_TX_ENA))); - - /* dummy read to ensure writing */ - GM_IN16(IoC, Port, GM_GP_CTRL, &Word); - } -#endif /* YUKON */ - -} /* SkMacRxTxDisable */ - - -/****************************************************************************** - * - * SkMacIrqDisable() - Disable IRQ from MAC - * - * Description: sets the IRQ-mask to disable IRQ dep. on board type - * - * Returns: N/A - */ -void SkMacIrqDisable( -SK_AC *pAC, /* Adapter Context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; -#ifdef GENESIS - SK_U16 Word; -#endif - - pPrt = &pAC->GIni.GP[Port]; - -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - - /* disable all XMAC IRQs */ - XM_OUT16(IoC, Port, XM_IMSK, 0xffff); - - /* Disable all PHY interrupts */ - switch (pPrt->PhyType) { - case SK_PHY_BCOM: - /* Make sure that PHY is initialized */ - if (pPrt->PState != SK_PRT_RESET) { - /* NOT allowed if BCOM is in RESET state */ - /* Workaround BCOM Errata (#10523) all BCom */ - /* Disable Power Management if link is down */ - SkXmPhyRead(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, &Word); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_AUX_CTRL, - (SK_U16)(Word | PHY_B_AC_DIS_PM)); - SkXmPhyWrite(pAC, IoC, Port, PHY_BCOM_INT_MASK, 0xffff); - } - break; -#ifdef OTHER_PHY - case SK_PHY_LONE: - SkXmPhyWrite(pAC, IoC, Port, PHY_LONE_INT_ENAB, 0); - break; - case SK_PHY_NAT: - /* todo: National - SkXmPhyWrite(pAC, IoC, Port, PHY_NAT_INT_MASK, 0xffff); */ - break; -#endif /* OTHER_PHY */ - } - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* disable all GMAC IRQs */ - SK_OUT8(IoC, GMAC_IRQ_MSK, 0); - -#ifndef VCPU - /* Disable all PHY interrupts */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_INT_MASK, 0); -#endif /* VCPU */ - } -#endif /* YUKON */ - -} /* SkMacIrqDisable */ - - -#ifdef SK_DIAG -/****************************************************************************** - * - * SkXmSendCont() - Enable / Disable Send Continuous Mode - * - * Description: enable / disable Send Continuous Mode on XMAC - * - * Returns: - * nothing - */ -void SkXmSendCont( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U32 MdReg; - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - if (Enable) { - MdReg |= XM_MD_TX_CONT; - } - else { - MdReg &= ~XM_MD_TX_CONT; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - -} /* SkXmSendCont */ - - -/****************************************************************************** - * - * SkMacTimeStamp() - Enable / Disable Time Stamp - * - * Description: enable / disable Time Stamp generation for Rx packets - * - * Returns: - * nothing - */ -void SkMacTimeStamp( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL Enable) /* Enable / Disable */ -{ - SK_U32 MdReg; - SK_U8 TimeCtrl; - - if (pAC->GIni.GIGenesis) { - - XM_IN32(IoC, Port, XM_MODE, &MdReg); - - if (Enable) { - MdReg |= XM_MD_ATS; - } - else { - MdReg &= ~XM_MD_ATS; - } - /* setup Mode Register */ - XM_OUT32(IoC, Port, XM_MODE, MdReg); - } - else { - if (Enable) { - TimeCtrl = GMT_ST_START | GMT_ST_CLR_IRQ; - } - else { - TimeCtrl = GMT_ST_STOP | GMT_ST_CLR_IRQ; - } - /* Start/Stop Time Stamp Timer */ - SK_OUT8(IoC, GMAC_TI_ST_CTRL, TimeCtrl); - } - -} /* SkMacTimeStamp*/ - -#else /* !SK_DIAG */ - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmAutoNegLipaXmac() - Decides whether Link Partner could do auto-neg - * - * This function analyses the Interrupt status word. If any of the - * Auto-negotiating interrupt bits are set, the PLipaAutoNeg variable - * is set true. - */ -void SkXmAutoNegLipaXmac( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus) /* Interrupt Status word to analyse */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && - (IStatus & (XM_IS_LIPA_RC | XM_IS_RX_PAGE | XM_IS_AND)) != 0) { - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegLipa: AutoNeg detected on Port %d, IStatus=0x%04X\n", - Port, IStatus)); - pPrt->PLipaAutoNeg = SK_LIPA_AUTO; - } -} /* SkXmAutoNegLipaXmac */ -#endif /* GENESIS */ - - -/****************************************************************************** - * - * SkMacAutoNegLipaPhy() - Decides whether Link Partner could do auto-neg - * - * This function analyses the PHY status word. - * If any of the Auto-negotiating bits are set, the PLipaAutoNeg variable - * is set true. - */ -void SkMacAutoNegLipaPhy( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_U16 PhyStat) /* PHY Status word to analyse */ -{ - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PLipaAutoNeg != SK_LIPA_AUTO && - (PhyStat & PHY_ST_AN_OVER) != 0) { - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("AutoNegLipa: AutoNeg detected on Port %d, PhyStat=0x%04X\n", - Port, PhyStat)); - pPrt->PLipaAutoNeg = SK_LIPA_AUTO; - } -} /* SkMacAutoNegLipaPhy */ - - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmIrq() - Interrupt Service Routine - * - * Description: services an Interrupt Request of the XMAC - * - * Note: - * With an external PHY, some interrupt bits are not meaningfull any more: - * - LinkAsyncEvent (bit #14) XM_IS_LNK_AE - * - LinkPartnerReqConfig (bit #10) XM_IS_LIPA_RC - * - Page Received (bit #9) XM_IS_RX_PAGE - * - NextPageLoadedForXmt (bit #8) XM_IS_TX_PAGE - * - AutoNegDone (bit #7) XM_IS_AND - * Also probably not valid any more is the GP0 input bit: - * - GPRegisterBit0set XM_IS_INP_ASS - * - * Returns: - * nothing - */ -static void SkXmIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_EVPARA Para; - SK_U16 IStatus; /* Interrupt status read from the XMAC */ - SK_U16 IStatus2; -#ifdef SK_SLIM - SK_U64 OverflowStatus; -#endif - - pPrt = &pAC->GIni.GP[Port]; - - XM_IN16(IoC, Port, XM_ISRC, &IStatus); - - /* LinkPartner Auto-negable? */ - if (pPrt->PhyType == SK_PHY_XMAC) { - SkXmAutoNegLipaXmac(pAC, IoC, Port, IStatus); - } - else { - /* mask bits that are not used with ext. PHY */ - IStatus &= ~(XM_IS_LNK_AE | XM_IS_LIPA_RC | - XM_IS_RX_PAGE | XM_IS_TX_PAGE | - XM_IS_AND | XM_IS_INP_ASS); - } - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("XmacIrq Port %d Isr 0x%04X\n", Port, IStatus)); - - if (!pPrt->PHWLinkUp) { - /* Spurious XMAC interrupt */ - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: spurious interrupt on Port %d\n", Port)); - return; - } - - if ((IStatus & XM_IS_INP_ASS) != 0) { - /* Reread ISR Register if link is not in sync */ - XM_IN16(IoC, Port, XM_ISRC, &IStatus2); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: Link async. Double check Port %d 0x%04X 0x%04X\n", - Port, IStatus, IStatus2)); - IStatus &= ~XM_IS_INP_ASS; - IStatus |= IStatus2; - } - - if ((IStatus & XM_IS_LNK_AE) != 0) { - /* not used, GP0 is used instead */ - } - - if ((IStatus & XM_IS_TX_ABORT) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_FRC_INT) != 0) { - /* not used, use ASIC IRQ instead if needed */ - } - - if ((IStatus & (XM_IS_INP_ASS | XM_IS_LIPA_RC | XM_IS_RX_PAGE)) != 0) { - SkHWLinkDown(pAC, IoC, Port); - - /* Signal to RLMT */ - Para.Para32[0] = (SK_U32)Port; - SkEventQueue(pAC, SKGE_RLMT, SK_RLMT_LINK_DOWN, Para); - - /* Start workaround Errata #2 timer */ - SkTimerStart(pAC, IoC, &pPrt->PWaTimer, SK_WA_INA_TIME, - SKGE_HWAC, SK_HWEV_WATIM, Para); - } - - if ((IStatus & XM_IS_RX_PAGE) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_TX_PAGE) != 0) { - /* not used */ - } - - if ((IStatus & XM_IS_AND) != 0) { - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("SkXmIrq: AND on link that is up Port %d\n", Port)); - } - - if ((IStatus & XM_IS_TSC_OV) != 0) { - /* not used */ - } - - /* Combined Tx & Rx Counter Overflow SIRQ Event */ - if ((IStatus & (XM_IS_RXC_OV | XM_IS_TXC_OV)) != 0) { -#ifdef SK_SLIM - SkXmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus); -#else - Para.Para32[0] = (SK_U32)Port; - Para.Para32[1] = (SK_U32)IStatus; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); -#endif /* SK_SLIM */ - } - - if ((IStatus & XM_IS_RXF_OV) != 0) { - /* normal situation -> no effect */ -#ifdef DEBUG - pPrt->PRxOverCnt++; -#endif /* DEBUG */ - } - - if ((IStatus & XM_IS_TXF_UR) != 0) { - /* may NOT happen -> error log */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); - } - - if ((IStatus & XM_IS_TX_COMP) != 0) { - /* not served here */ - } - - if ((IStatus & XM_IS_RX_COMP) != 0) { - /* not served here */ - } -} /* SkXmIrq */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmIrq() - Interrupt Service Routine - * - * Description: services an Interrupt Request of the GMAC - * - * Note: - * - * Returns: - * nothing - */ -static void SkGmIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U8 IStatus; /* Interrupt status */ -#ifdef SK_SLIM - SK_U64 OverflowStatus; -#else - SK_EVPARA Para; -#endif - - pPrt = &pAC->GIni.GP[Port]; - - SK_IN8(IoC, GMAC_IRQ_SRC, &IStatus); - -#ifdef XXX - /* LinkPartner Auto-negable? */ - SkMacAutoNegLipaPhy(pAC, IoC, Port, IStatus); -#endif /* XXX */ - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_IRQ, - ("GmacIrq Port %d Isr 0x%04X\n", Port, IStatus)); - - /* Combined Tx & Rx Counter Overflow SIRQ Event */ - if (IStatus & (GM_IS_RX_CO_OV | GM_IS_TX_CO_OV)) { - /* these IRQs will be cleared by reading GMACs register */ -#ifdef SK_SLIM - SkGmOverflowStatus(pAC, IoC, Port, IStatus, &OverflowStatus); -#else - Para.Para32[0] = (SK_U32)Port; - Para.Para32[1] = (SK_U32)IStatus; - SkPnmiEvent(pAC, IoC, SK_PNMI_EVT_SIRQ_OVERFLOW, Para); -#endif - } - - if (IStatus & GM_IS_RX_FF_OR) { - /* clear GMAC Rx FIFO Overrun IRQ */ - SK_OUT8(IoC, MR_ADDR(Port, RX_GMF_CTRL_T), (SK_U8)GMF_CLI_RX_FO); -#ifdef DEBUG - pPrt->PRxOverCnt++; -#endif /* DEBUG */ - } - - if (IStatus & GM_IS_TX_FF_UR) { - /* clear GMAC Tx FIFO Underrun IRQ */ - SK_OUT8(IoC, MR_ADDR(Port, TX_GMF_CTRL_T), (SK_U8)GMF_CLI_TX_FU); - /* may NOT happen -> error log */ - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_SIRQ_E020, SKERR_SIRQ_E020MSG); - } - - if (IStatus & GM_IS_TX_COMPL) { - /* not served here */ - } - - if (IStatus & GM_IS_RX_COMPL) { - /* not served here */ - } -} /* SkGmIrq */ -#endif /* YUKON */ - - -/****************************************************************************** - * - * SkMacIrq() - Interrupt Service Routine for MAC - * - * Description: calls the Interrupt Service Routine dep. on board type - * - * Returns: - * nothing - */ -void SkMacIrq( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port) /* Port Index (MAC_1 + n) */ -{ -#ifdef GENESIS - if (pAC->GIni.GIGenesis) { - /* IRQ from XMAC */ - SkXmIrq(pAC, IoC, Port); - } -#endif /* GENESIS */ - -#ifdef YUKON - if (pAC->GIni.GIYukon) { - /* IRQ from GMAC */ - SkGmIrq(pAC, IoC, Port); - } -#endif /* YUKON */ - -} /* SkMacIrq */ - -#endif /* !SK_DIAG */ - -#ifdef GENESIS -/****************************************************************************** - * - * SkXmUpdateStats() - Force the XMAC to output the current statistic - * - * Description: - * The XMAC holds its statistic internally. To obtain the current - * values a command must be sent so that the statistic data will - * be written to a predefined memory area on the adapter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmUpdateStats( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - SK_GEPORT *pPrt; - SK_U16 StatReg; - int WaitIndex; - - pPrt = &pAC->GIni.GP[Port]; - WaitIndex = 0; - - /* Send an update command to XMAC specified */ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); - - /* - * It is an auto-clearing register. If the command bits - * went to zero again, the statistics are transferred. - * Normally the command should be executed immediately. - * But just to be sure we execute a loop. - */ - do { - - XM_IN16(IoC, Port, XM_STAT_CMD, &StatReg); - - if (++WaitIndex > 10) { - - SK_ERR_LOG(pAC, SK_ERRCL_HW, SKERR_HWI_E021, SKERR_HWI_E021MSG); - - return(1); - } - } while ((StatReg & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) != 0); - - return(0); -} /* SkXmUpdateStats */ - - -/****************************************************************************** - * - * SkXmMacStatistic() - Get XMAC counter value - * - * Description: - * Gets the 32bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * must be counted in software by monitoring counter overflow interrupts. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmMacStatistic( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 StatAddr, /* MIB counter base address */ -SK_U32 SK_FAR *pVal) /* ptr to return statistic value */ -{ - if ((StatAddr < XM_TXF_OK) || (StatAddr > XM_RXF_MAX_SZ)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); - - return(1); - } - - XM_IN32(IoC, Port, StatAddr, pVal); - - return(0); -} /* SkXmMacStatistic */ - - -/****************************************************************************** - * - * SkXmResetCounter() - Clear MAC statistic counter - * - * Description: - * Force the XMAC to clear its statistic counter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmResetCounter( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* Clear two times according to Errata #3 */ - XM_OUT16(IoC, Port, XM_STAT_CMD, XM_SC_CLR_RXC | XM_SC_CLR_TXC); - - return(0); -} /* SkXmResetCounter */ - - -/****************************************************************************** - * - * SkXmOverflowStatus() - Gets the status of counter overflow interrupt - * - * Description: - * Checks the source causing an counter overflow interrupt. On success the - * resulting counter overflow status is written to , whereas the - * upper dword stores the XMAC ReceiveCounterEvent register and the lower - * dword the XMAC TransmitCounterEvent register. - * - * Note: - * For XMAC the interrupt source is a self-clearing register, so the source - * must be checked only once. SIRQ module does another check to be sure - * that no interrupt get lost during process time. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkXmOverflowStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus, /* Interupt Status from MAC */ -SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */ -{ - SK_U64 Status; /* Overflow status */ - SK_U32 RegVal; - - Status = 0; - - if ((IStatus & XM_IS_RXC_OV) != 0) { - - XM_IN32(IoC, Port, XM_RX_CNT_EV, &RegVal); - Status |= (SK_U64)RegVal << 32; - } - - if ((IStatus & XM_IS_TXC_OV) != 0) { - - XM_IN32(IoC, Port, XM_TX_CNT_EV, &RegVal); - Status |= (SK_U64)RegVal; - } - - *pStatus = Status; - - return(0); -} /* SkXmOverflowStatus */ -#endif /* GENESIS */ - - -#ifdef YUKON -/****************************************************************************** - * - * SkGmUpdateStats() - Force the GMAC to output the current statistic - * - * Description: - * Empty function for GMAC. Statistic data is accessible in direct way. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmUpdateStats( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - return(0); -} - - -/****************************************************************************** - * - * SkGmMacStatistic() - Get GMAC counter value - * - * Description: - * Gets the 32bit counter value. Except for the octet counters - * the lower 32bit are counted in hardware and the upper 32bit - * must be counted in software by monitoring counter overflow interrupts. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmMacStatistic( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 StatAddr, /* MIB counter base address */ -SK_U32 SK_FAR *pVal) /* ptr to return statistic value */ -{ - - if ((StatAddr < GM_RXF_UC_OK) || (StatAddr > GM_TXE_FIFO_UR)) { - - SK_ERR_LOG(pAC, SK_ERRCL_SW, SKERR_HWI_E022, SKERR_HWI_E022MSG); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("SkGmMacStat: wrong MIB counter 0x%04X\n", StatAddr)); - return(1); - } - - GM_IN32(IoC, Port, StatAddr, pVal); - - return(0); -} /* SkGmMacStatistic */ - - -/****************************************************************************** - * - * SkGmResetCounter() - Clear MAC statistic counter - * - * Description: - * Force GMAC to clear its statistic counter. - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmResetCounter( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port) /* Port Index (MAC_1 + n) */ -{ - SK_U16 Reg; /* Phy Address Register */ - SK_U16 Word; - int i; - - GM_IN16(IoC, Port, GM_PHY_ADDR, &Reg); - - /* set MIB Clear Counter Mode */ - GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg | GM_PAR_MIB_CLR); - - /* read all MIB Counters with Clear Mode set */ - for (i = 0; i < GM_MIB_CNT_SIZE; i++) { - /* the reset is performed only when the lower 16 bits are read */ - GM_IN16(IoC, Port, GM_MIB_CNT_BASE + 8*i, &Word); - } - - /* clear MIB Clear Counter Mode */ - GM_OUT16(IoC, Port, GM_PHY_ADDR, Reg); - - return(0); -} /* SkGmResetCounter */ - - -/****************************************************************************** - * - * SkGmOverflowStatus() - Gets the status of counter overflow interrupt - * - * Description: - * Checks the source causing an counter overflow interrupt. On success the - * resulting counter overflow status is written to , whereas the - * the following bit coding is used: - * 63:56 - unused - * 55:48 - TxRx interrupt register bit7:0 - * 32:47 - Rx interrupt register - * 31:24 - unused - * 23:16 - TxRx interrupt register bit15:8 - * 15:0 - Tx interrupt register - * - * Returns: - * 0: success - * 1: something went wrong - */ -int SkGmOverflowStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -unsigned int Port, /* Port Index (MAC_1 + n) */ -SK_U16 IStatus, /* Interupt Status from MAC */ -SK_U64 SK_FAR *pStatus) /* ptr for return overflow status value */ -{ - SK_U64 Status; /* Overflow status */ - SK_U16 RegVal; - - Status = 0; - - if ((IStatus & GM_IS_RX_CO_OV) != 0) { - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_RX_IRQ_SRC, &RegVal); - Status |= (SK_U64)RegVal << 32; - } - - if ((IStatus & GM_IS_TX_CO_OV) != 0) { - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_TX_IRQ_SRC, &RegVal); - Status |= (SK_U64)RegVal; - } - - /* this register is self-clearing after read */ - GM_IN16(IoC, Port, GM_TR_IRQ_SRC, &RegVal); - /* Rx overflow interrupt register bits (LoByte)*/ - Status |= (SK_U64)((SK_U8)RegVal) << 48; - /* Tx overflow interrupt register bits (HiByte)*/ - Status |= (SK_U64)(RegVal >> 8) << 16; - - *pStatus = Status; - - return(0); -} /* SkGmOverflowStatus */ - - -#ifndef SK_SLIM -/****************************************************************************** - * - * SkGmCableDiagStatus() - Starts / Gets status of cable diagnostic test - * - * Description: - * starts the cable diagnostic test if 'StartTest' is true - * gets the results if 'StartTest' is true - * - * NOTE: this test is meaningful only when link is down - * - * Returns: - * 0: success - * 1: no YUKON copper - * 2: test in progress - */ -int SkGmCableDiagStatus( -SK_AC *pAC, /* adapter context */ -SK_IOC IoC, /* IO context */ -int Port, /* Port Index (MAC_1 + n) */ -SK_BOOL StartTest) /* flag for start / get result */ -{ - int i; - SK_U16 RegVal; - SK_GEPORT *pPrt; - - pPrt = &pAC->GIni.GP[Port]; - - if (pPrt->PhyType != SK_PHY_MARV_COPPER) { - - return(1); - } - - if (StartTest) { - /* only start the cable test */ - if ((pPrt->PhyId1 & PHY_I1_REV_MSK) < 4) { - /* apply TDR workaround from Marvell */ - SkGmPhyWrite(pAC, IoC, Port, 29, 0x001e); - - SkGmPhyWrite(pAC, IoC, Port, 30, 0xcc00); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc800); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc400); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc000); - SkGmPhyWrite(pAC, IoC, Port, 30, 0xc100); - } - - /* set address to 0 for MDI[0] */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, 0); - - /* Read Cable Diagnostic Reg */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - /* start Cable Diagnostic Test */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, - (SK_U16)(RegVal | PHY_M_CABD_ENA_TEST)); - - return(0); - } - - /* Read Cable Diagnostic Reg */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - SK_DBG_MSG(pAC, SK_DBGMOD_HWM, SK_DBGCAT_CTRL, - ("PHY Cable Diag.=0x%04X\n", RegVal)); - - if ((RegVal & PHY_M_CABD_ENA_TEST) != 0) { - /* test is running */ - return(2); - } - - /* get the test results */ - for (i = 0; i < 4; i++) { - /* set address to i for MDI[i] */ - SkGmPhyWrite(pAC, IoC, Port, PHY_MARV_EXT_ADR, (SK_U16)i); - - /* get Cable Diagnostic values */ - SkGmPhyRead(pAC, IoC, Port, PHY_MARV_CABLE_DIAG, &RegVal); - - pPrt->PMdiPairLen[i] = (SK_U8)(RegVal & PHY_M_CABD_DIST_MSK); - - pPrt->PMdiPairSts[i] = (SK_U8)((RegVal & PHY_M_CABD_STAT_MSK) >> 13); - } - - return(0); -} /* SkGmCableDiagStatus */ -#endif /* !SK_SLIM */ -#endif /* YUKON */ - -/* End of file */ -- cgit v1.2.3 From d28a79326a4028dbb1755b8efe6daa915d8bfeea Mon Sep 17 00:00:00 2001 From: Manish Ahuja Date: Sat, 22 Mar 2008 10:33:10 +1100 Subject: [POWERPC] pseries: phyp dump: Documentation Basic documentation for hypervisor-assisted dump. Signed-off-by: Linas Vepstas Signed-off-by: Manish Ahuja Signed-off-by: Paul Mackerras --- Documentation/powerpc/phyp-assisted-dump.txt | 127 +++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 Documentation/powerpc/phyp-assisted-dump.txt (limited to 'Documentation') diff --git a/Documentation/powerpc/phyp-assisted-dump.txt b/Documentation/powerpc/phyp-assisted-dump.txt new file mode 100644 index 000000000000..c4682b982a2e --- /dev/null +++ b/Documentation/powerpc/phyp-assisted-dump.txt @@ -0,0 +1,127 @@ + + Hypervisor-Assisted Dump + ------------------------ + November 2007 + +The goal of hypervisor-assisted dump is to enable the dump of +a crashed system, and to do so from a fully-reset system, and +to minimize the total elapsed time until the system is back +in production use. + +As compared to kdump or other strategies, hypervisor-assisted +dump offers several strong, practical advantages: + +-- Unlike kdump, the system has been reset, and loaded + with a fresh copy of the kernel. In particular, + PCI and I/O devices have been reinitialized and are + in a clean, consistent state. +-- As the dump is performed, the dumped memory becomes + immediately available to the system for normal use. +-- After the dump is completed, no further reboots are + required; the system will be fully usable, and running + in it's normal, production mode on it normal kernel. + +The above can only be accomplished by coordination with, +and assistance from the hypervisor. The procedure is +as follows: + +-- When a system crashes, the hypervisor will save + the low 256MB of RAM to a previously registered + save region. It will also save system state, system + registers, and hardware PTE's. + +-- After the low 256MB area has been saved, the + hypervisor will reset PCI and other hardware state. + It will *not* clear RAM. It will then launch the + bootloader, as normal. + +-- The freshly booted kernel will notice that there + is a new node (ibm,dump-kernel) in the device tree, + indicating that there is crash data available from + a previous boot. It will boot into only 256MB of RAM, + reserving the rest of system memory. + +-- Userspace tools will parse /sys/kernel/release_region + and read /proc/vmcore to obtain the contents of memory, + which holds the previous crashed kernel. The userspace + tools may copy this info to disk, or network, nas, san, + iscsi, etc. as desired. + + For Example: the values in /sys/kernel/release-region + would look something like this (address-range pairs). + CPU:0x177fee000-0x10000: HPTE:0x177ffe020-0x1000: / + DUMP:0x177fff020-0x10000000, 0x10000000-0x16F1D370A + +-- As the userspace tools complete saving a portion of + dump, they echo an offset and size to + /sys/kernel/release_region to release the reserved + memory back to general use. + + An example of this is: + "echo 0x40000000 0x10000000 > /sys/kernel/release_region" + which will release 256MB at the 1GB boundary. + +Please note that the hypervisor-assisted dump feature +is only available on Power6-based systems with recent +firmware versions. + +Implementation details: +---------------------- + +During boot, a check is made to see if firmware supports +this feature on this particular machine. If it does, then +we check to see if a active dump is waiting for us. If yes +then everything but 256 MB of RAM is reserved during early +boot. This area is released once we collect a dump from user +land scripts that are run. If there is dump data, then +the /sys/kernel/release_region file is created, and +the reserved memory is held. + +If there is no waiting dump data, then only the highest +256MB of the ram is reserved as a scratch area. This area +is *not* released: this region will be kept permanently +reserved, so that it can act as a receptacle for a copy +of the low 256MB in the case a crash does occur. See, +however, "open issues" below, as to whether +such a reserved region is really needed. + +Currently the dump will be copied from /proc/vmcore to a +a new file upon user intervention. The starting address +to be read and the range for each data point in provided +in /sys/kernel/release_region. + +The tools to examine the dump will be same as the ones +used for kdump. + +General notes: +-------------- +Security: please note that there are potential security issues +with any sort of dump mechanism. In particular, plaintext +(unencrypted) data, and possibly passwords, may be present in +the dump data. Userspace tools must take adequate precautions to +preserve security. + +Open issues/ToDo: +------------ + o The various code paths that tell the hypervisor that a crash + occurred, vs. it simply being a normal reboot, should be + reviewed, and possibly clarified/fixed. + + o Instead of using /sys/kernel, should there be a /sys/dump + instead? There is a dump_subsys being created by the s390 code, + perhaps the pseries code should use a similar layout as well. + + o Is reserving a 256MB region really required? The goal of + reserving a 256MB scratch area is to make sure that no + important crash data is clobbered when the hypervisor + save low mem to the scratch area. But, if one could assure + that nothing important is located in some 256MB area, then + it would not need to be reserved. Something that can be + improved in subsequent versions. + + o Still working the kdump team to integrate this with kdump, + some work remains but this would not affect the current + patches. + + o Still need to write a shell script, to copy the dump away. + Currently I am parsing it manually. -- cgit v1.2.3 From ecc6cd73b7ccfa10c1f07d017fc7f62fe78eaab5 Mon Sep 17 00:00:00 2001 From: David Gibson Date: Tue, 26 Feb 2008 11:43:20 +1100 Subject: [POWERPC] Start removing linux,network-index in favour of aliases This patch alters the bootwrapper for a number of machines (roubhly all 4xx based cuboot or treeboot platforms) to use aliases instead of the linux,network-index hack to work out which MAC address to attach to which ethernet device node. The now obsolete linux,network-index properties are removed from the corresponding device trees. This won't break backwards compatiblity, because in cases where this fixup code is relevant, the device tree is part of the kernel image. The references to linux,network-index are removed from booting-without-of.txt. Not only is it now deprecated, but as a hack applicable only when the device tree blob and fixup code were in the same image, this property never belonged in booting-without-of.txt which describes the interface between the kernel and firmware or bootloaders which produce a device tree. By the time the device tree reaches the kernel, all the MAC addresses must be fully filled in. Signed-off-by: David Gibson Signed-off-by: Josh Boyer --- Documentation/powerpc/booting-without-of.txt | 16 ---------------- arch/powerpc/boot/bamboo.c | 3 ++- arch/powerpc/boot/cuboot-rainier.c | 3 ++- arch/powerpc/boot/cuboot-sequoia.c | 3 ++- arch/powerpc/boot/cuboot-taishan.c | 3 ++- arch/powerpc/boot/cuboot-warp.c | 2 +- arch/powerpc/boot/dts/bamboo.dts | 2 -- arch/powerpc/boot/dts/ebony.dts | 2 -- arch/powerpc/boot/dts/rainier.dts | 2 -- arch/powerpc/boot/dts/sequoia.dts | 2 -- arch/powerpc/boot/dts/taishan.dts | 4 ---- arch/powerpc/boot/dts/walnut.dts | 1 - arch/powerpc/boot/dts/warp.dts | 1 - arch/powerpc/boot/ebony.c | 3 ++- arch/powerpc/boot/treeboot-walnut.c | 2 +- 15 files changed, 12 insertions(+), 37 deletions(-) (limited to 'Documentation') diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 7b4e8a70882c..1df9d4cfc0e6 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -1269,10 +1269,6 @@ platforms are moved over to use the flattened-device-tree model. Recommended properties: - - linux,network-index : This is the intended "index" of this - network device. This is used by the bootwrapper to interpret - MAC addresses passed by the firmware when no information other - than indices is available to associate an address with a device. - phy-connection-type : a string naming the controller/PHY interface type, i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id", "sgmii", "tbi", or "rtbi". This property is only really needed if the connection @@ -1667,10 +1663,6 @@ platforms are moved over to use the flattened-device-tree model. - phy-handle : The phandle for the PHY connected to this controller. Recommended properties: - - linux,network-index : This is the intended "index" of this - network device. This is used by the bootwrapper to interpret - MAC addresses passed by the firmware when no information other - than indices is available to associate an address with a device. - phy-connection-type : a string naming the controller/PHY interface type, i.e., "mii" (default), "rmii", "gmii", "rgmii", "rgmii-id" (Internal Delay), "rgmii-txid" (delay on TX only), "rgmii-rxid" (delay on RX only), @@ -1995,7 +1987,6 @@ platforms are moved over to use the flattened-device-tree model. interrupts = <20 8>; interrupt-parent = <&PIC>; phy-handle = <&PHY0>; - linux,network-index = <0>; fsl,cpm-command = <12000300>; }; @@ -2217,12 +2208,6 @@ platforms are moved over to use the flattened-device-tree model. EMAC, that is the content of the current (bogus) "phy-port" property. - Recommended properties: - - linux,network-index : This is the intended "index" of this - network device. This is used by the bootwrapper to interpret - MAC addresses passed by the firmware when no information other - than indices is available to associate an address with a device. - Optional properties: - phy-address : 1 cell, optional, MDIO address of the PHY. If absent, a search is performed. @@ -2246,7 +2231,6 @@ platforms are moved over to use the flattened-device-tree model. Example: EMAC0: ethernet@40000800 { - linux,network-index = <0>; device_type = "network"; compatible = "ibm,emac-440gp", "ibm,emac"; interrupt-parent = <&UIC1>; diff --git a/arch/powerpc/boot/bamboo.c b/arch/powerpc/boot/bamboo.c index 54b33f1500e2..b82cacbc60db 100644 --- a/arch/powerpc/boot/bamboo.c +++ b/arch/powerpc/boot/bamboo.c @@ -33,7 +33,8 @@ static void bamboo_fixups(void) ibm440ep_fixup_clocks(sysclk, 11059200, 25000000); ibm4xx_sdram_fixup_memsize(); ibm4xx_quiesce_eth((u32 *)0xef600e00, (u32 *)0xef600f00); - dt_fixup_mac_addresses(bamboo_mac0, bamboo_mac1); + dt_fixup_mac_address_by_alias("ethernet0", bamboo_mac0); + dt_fixup_mac_address_by_alias("ethernet1", bamboo_mac1); } void bamboo_init(void *mac0, void *mac1) diff --git a/arch/powerpc/boot/cuboot-rainier.c b/arch/powerpc/boot/cuboot-rainier.c index cf452b66dce8..0a3fddee54df 100644 --- a/arch/powerpc/boot/cuboot-rainier.c +++ b/arch/powerpc/boot/cuboot-rainier.c @@ -42,7 +42,8 @@ static void rainier_fixups(void) ibm440ep_fixup_clocks(sysclk, 11059200, 50000000); ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); ibm4xx_denali_fixup_memsize(); - dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr); + dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr); + dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr); } void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, diff --git a/arch/powerpc/boot/cuboot-sequoia.c b/arch/powerpc/boot/cuboot-sequoia.c index f555575a44de..caf8f2e842ea 100644 --- a/arch/powerpc/boot/cuboot-sequoia.c +++ b/arch/powerpc/boot/cuboot-sequoia.c @@ -42,7 +42,8 @@ static void sequoia_fixups(void) ibm440ep_fixup_clocks(sysclk, 11059200, 50000000); ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); ibm4xx_denali_fixup_memsize(); - dt_fixup_mac_addresses(&bd.bi_enetaddr, &bd.bi_enet1addr); + dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr); + dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr); } void platform_init(unsigned long r3, unsigned long r4, unsigned long r5, diff --git a/arch/powerpc/boot/cuboot-taishan.c b/arch/powerpc/boot/cuboot-taishan.c index b55b80467eed..9bc906a754dd 100644 --- a/arch/powerpc/boot/cuboot-taishan.c +++ b/arch/powerpc/boot/cuboot-taishan.c @@ -40,7 +40,8 @@ static void taishan_fixups(void) ibm4xx_sdram_fixup_memsize(); - dt_fixup_mac_addresses(bd.bi_enetaddr, bd.bi_enet1addr); + dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr); + dt_fixup_mac_address_by_alias("ethernet1", bd.bi_enet1addr); ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); } diff --git a/arch/powerpc/boot/cuboot-warp.c b/arch/powerpc/boot/cuboot-warp.c index 3db93e85e9ea..eb108a877492 100644 --- a/arch/powerpc/boot/cuboot-warp.c +++ b/arch/powerpc/boot/cuboot-warp.c @@ -24,7 +24,7 @@ static void warp_fixups(void) ibm440ep_fixup_clocks(sysclk, 11059200, 50000000); ibm4xx_sdram_fixup_memsize(); ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); - dt_fixup_mac_addresses(&bd.bi_enetaddr); + dt_fixup_mac_address_by_alias("ethernet0", bd.bi_enetaddr); } diff --git a/arch/powerpc/boot/dts/bamboo.dts b/arch/powerpc/boot/dts/bamboo.dts index 7dc37c9a7446..ba2521bdaab1 100644 --- a/arch/powerpc/boot/dts/bamboo.dts +++ b/arch/powerpc/boot/dts/bamboo.dts @@ -204,7 +204,6 @@ }; EMAC0: ethernet@ef600e00 { - linux,network-index = <0>; device_type = "network"; compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac"; interrupt-parent = <&UIC1>; @@ -225,7 +224,6 @@ }; EMAC1: ethernet@ef600f00 { - linux,network-index = <1>; device_type = "network"; compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac"; interrupt-parent = <&UIC1>; diff --git a/arch/powerpc/boot/dts/ebony.dts b/arch/powerpc/boot/dts/ebony.dts index 0b000cb7ed8b..5079dc890e0e 100644 --- a/arch/powerpc/boot/dts/ebony.dts +++ b/arch/powerpc/boot/dts/ebony.dts @@ -241,7 +241,6 @@ }; EMAC0: ethernet@40000800 { - linux,network-index = <0>; device_type = "network"; compatible = "ibm,emac-440gp", "ibm,emac"; interrupt-parent = <&UIC1>; @@ -261,7 +260,6 @@ zmii-channel = <0>; }; EMAC1: ethernet@40000900 { - linux,network-index = <1>; device_type = "network"; compatible = "ibm,emac-440gp", "ibm,emac"; interrupt-parent = <&UIC1>; diff --git a/arch/powerpc/boot/dts/rainier.dts b/arch/powerpc/boot/dts/rainier.dts index f947c75a2e94..9f6f58b2e077 100644 --- a/arch/powerpc/boot/dts/rainier.dts +++ b/arch/powerpc/boot/dts/rainier.dts @@ -254,7 +254,6 @@ }; EMAC0: ethernet@ef600e00 { - linux,network-index = <0>; device_type = "network"; compatible = "ibm,emac-440grx", "ibm,emac-440epx", "ibm,emac4"; interrupt-parent = <&EMAC0>; @@ -284,7 +283,6 @@ }; EMAC1: ethernet@ef600f00 { - linux,network-index = <1>; device_type = "network"; compatible = "ibm,emac-440grx", "ibm,emac-440epx", "ibm,emac4"; interrupt-parent = <&EMAC1>; diff --git a/arch/powerpc/boot/dts/sequoia.dts b/arch/powerpc/boot/dts/sequoia.dts index 8db9515d7dc3..675026bf1fb0 100644 --- a/arch/powerpc/boot/dts/sequoia.dts +++ b/arch/powerpc/boot/dts/sequoia.dts @@ -269,7 +269,6 @@ }; EMAC0: ethernet@ef600e00 { - linux,network-index = <0>; device_type = "network"; compatible = "ibm,emac-440epx", "ibm,emac4"; interrupt-parent = <&EMAC0>; @@ -299,7 +298,6 @@ }; EMAC1: ethernet@ef600f00 { - linux,network-index = <1>; device_type = "network"; compatible = "ibm,emac-440epx", "ibm,emac4"; interrupt-parent = <&EMAC1>; diff --git a/arch/powerpc/boot/dts/taishan.dts b/arch/powerpc/boot/dts/taishan.dts index 8278068c802c..466c3f35ce13 100644 --- a/arch/powerpc/boot/dts/taishan.dts +++ b/arch/powerpc/boot/dts/taishan.dts @@ -235,7 +235,6 @@ EMAC0: ethernet@40000800 { unused = <1>; - linux,network-index = <2>; device_type = "network"; compatible = "ibm,emac-440gx", "ibm,emac4"; interrupt-parent = <&UIC1>; @@ -256,7 +255,6 @@ }; EMAC1: ethernet@40000900 { unused = <1>; - linux,network-index = <3>; device_type = "network"; compatible = "ibm,emac-440gx", "ibm,emac4"; interrupt-parent = <&UIC1>; @@ -277,7 +275,6 @@ }; EMAC2: ethernet@40000c00 { - linux,network-index = <0>; device_type = "network"; compatible = "ibm,emac-440gx", "ibm,emac4"; interrupt-parent = <&UIC2>; @@ -300,7 +297,6 @@ }; EMAC3: ethernet@40000e00 { - linux,network-index = <1>; device_type = "network"; compatible = "ibm,emac-440gx", "ibm,emac4"; interrupt-parent = <&UIC2>; diff --git a/arch/powerpc/boot/dts/walnut.dts b/arch/powerpc/boot/dts/walnut.dts index dcc21b0438e5..a328607c8f84 100644 --- a/arch/powerpc/boot/dts/walnut.dts +++ b/arch/powerpc/boot/dts/walnut.dts @@ -125,7 +125,6 @@ }; EMAC: ethernet@ef600800 { - linux,network-index = <0>; device_type = "network"; compatible = "ibm,emac-405gp", "ibm,emac"; interrupt-parent = <&UIC0>; diff --git a/arch/powerpc/boot/dts/warp.dts b/arch/powerpc/boot/dts/warp.dts index dc1499d30f43..b04a52e22bf5 100644 --- a/arch/powerpc/boot/dts/warp.dts +++ b/arch/powerpc/boot/dts/warp.dts @@ -204,7 +204,6 @@ }; EMAC0: ethernet@ef600e00 { - linux,network-index = <0>; device_type = "network"; compatible = "ibm,emac-440ep", "ibm,emac-440gp", "ibm,emac"; interrupt-parent = <&UIC1>; diff --git a/arch/powerpc/boot/ebony.c b/arch/powerpc/boot/ebony.c index f61364c47a76..5532ab3221dd 100644 --- a/arch/powerpc/boot/ebony.c +++ b/arch/powerpc/boot/ebony.c @@ -75,7 +75,8 @@ static void ebony_fixups(void) ibm440gp_fixup_clocks(sysclk, 6 * 1843200); ibm4xx_sdram_fixup_memsize(); - dt_fixup_mac_addresses(ebony_mac0, ebony_mac1); + dt_fixup_mac_address_by_alias("ethernet0", ebony_mac0); + dt_fixup_mac_address_by_alias("ethernet1", ebony_mac1); ibm4xx_fixup_ebc_ranges("/plb/opb/ebc"); ebony_flashsel_fixup(); } diff --git a/arch/powerpc/boot/treeboot-walnut.c b/arch/powerpc/boot/treeboot-walnut.c index 472e36605a52..097974e59fac 100644 --- a/arch/powerpc/boot/treeboot-walnut.c +++ b/arch/powerpc/boot/treeboot-walnut.c @@ -68,7 +68,7 @@ static void walnut_fixups(void) ibm4xx_quiesce_eth((u32 *)0xef600800, NULL); ibm4xx_fixup_ebc_ranges("/plb/ebc"); walnut_flashsel_fixup(); - dt_fixup_mac_addresses((u8 *) WALNUT_OPENBIOS_MAC_OFF); + dt_fixup_mac_address_by_alias("ethernet0", (u8 *) WALNUT_OPENBIOS_MAC_OFF); } void platform_init(void) -- cgit v1.2.3 From a78bfbfcfaca64e6198f164c43a60afc8a50e2c6 Mon Sep 17 00:00:00 2001 From: Robert Brose Date: Sat, 29 Mar 2008 07:20:23 +1100 Subject: [POWERPC] Add kernel parameter to set l3cr for MPC745x Old-world powermacs don't set L2CR or L3CR on processor upgrade cards. This simple patch allows the setting of L3CR via a kernel parameter (like the existing kernel parameter to set L2CR). Signed-off-by: Robert Brose Signed-off-by: Paul Mackerras --- Documentation/kernel-parameters.txt | 2 ++ arch/powerpc/kernel/setup_32.c | 12 ++++++++++++ 2 files changed, 14 insertions(+) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 508e2a2c9864..a1ff28e0872b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -931,6 +931,8 @@ and is between 256 and 4096 characters. It is defined in the file l2cr= [PPC] + l3cr= [PPC] + lapic [X86-32,APIC] Enable the local APIC even if BIOS disabled it. diff --git a/arch/powerpc/kernel/setup_32.c b/arch/powerpc/kernel/setup_32.c index cd870a823d18..eac936eb3190 100644 --- a/arch/powerpc/kernel/setup_32.c +++ b/arch/powerpc/kernel/setup_32.c @@ -172,6 +172,18 @@ int __init ppc_setup_l2cr(char *str) } __setup("l2cr=", ppc_setup_l2cr); +/* Checks "l3cr=xxxx" command-line option */ +int __init ppc_setup_l3cr(char *str) +{ + if (cpu_has_feature(CPU_FTR_L3CR)) { + unsigned long val = simple_strtoul(str, NULL, 0); + printk(KERN_INFO "l3cr set to %lx\n", val); + _set_L3CR(val); /* and enable it */ + } + return 1; +} +__setup("l3cr=", ppc_setup_l3cr); + #ifdef CONFIG_GENERIC_NVRAM /* Generic nvram hooks used by drivers/char/gen_nvram.c */ -- cgit v1.2.3 From a6c75b86ce9f01db4ea9912877b526c2dc4d2f0a Mon Sep 17 00:00:00 2001 From: Fenghua Yu Date: Fri, 14 Mar 2008 13:57:08 -0700 Subject: [IA64] Kernel parameter for max number of concurrent global TLB purges The patch defines kernel parameter "nptcg=". The parameter overrides max number of concurrent global TLB purges which is reported from either PAL_VM_SUMMARY or SAL PALO. Signed-off-by: Fenghua Yu Signed-off-by: Tony Luck --- Documentation/kernel-parameters.txt | 4 ++++ arch/ia64/kernel/efi.c | 2 +- arch/ia64/kernel/setup.c | 2 +- arch/ia64/mm/tlb.c | 46 +++++++++++++++++++++++++++++++++---- include/asm-ia64/sal.h | 4 ++++ 5 files changed, 51 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4cd1a5da80a4..be92e6165722 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1335,6 +1335,10 @@ and is between 256 and 4096 characters. It is defined in the file nowb [ARM] + nptcg= [IA64] Override max number of concurrent global TLB + purges which is reported from either PAL_VM_SUMMARY or + SAL PALO. + numa_zonelist_order= [KNL, BOOT] Select zonelist order for NUMA. one of ['zone', 'node', 'default'] can be specified This can be set from sysctl after boot. diff --git a/arch/ia64/kernel/efi.c b/arch/ia64/kernel/efi.c index 003cd09b0732..d45f215bc8fc 100644 --- a/arch/ia64/kernel/efi.c +++ b/arch/ia64/kernel/efi.c @@ -436,7 +436,7 @@ static void __init handle_palo(unsigned long palo_phys) return; } - setup_ptcg_sem(palo->max_tlb_purges, 1); + setup_ptcg_sem(palo->max_tlb_purges, NPTCG_FROM_PALO); } void diff --git a/arch/ia64/kernel/setup.c b/arch/ia64/kernel/setup.c index 1cbd26340d87..f798c0769d36 100644 --- a/arch/ia64/kernel/setup.c +++ b/arch/ia64/kernel/setup.c @@ -949,7 +949,7 @@ cpu_init (void) /* set ia64_ctx.max_rid to the maximum RID that is supported by all CPUs: */ if (ia64_pal_vm_summary(NULL, &vmi) == 0) { max_ctx = (1U << (vmi.pal_vm_info_2_s.rid_size - 3)) - 1; - setup_ptcg_sem(vmi.pal_vm_info_2_s.max_purges, 0); + setup_ptcg_sem(vmi.pal_vm_info_2_s.max_purges, NPTCG_FROM_PAL); } else { printk(KERN_WARNING "cpu_init: PAL VM summary failed, assuming 18 RID bits\n"); max_ctx = (1U << 15) - 1; /* use architected minimum */ diff --git a/arch/ia64/mm/tlb.c b/arch/ia64/mm/tlb.c index d41d6076ed03..1a8948fd0029 100644 --- a/arch/ia64/mm/tlb.c +++ b/arch/ia64/mm/tlb.c @@ -119,6 +119,27 @@ static u16 nptcg = 1; static int need_ptcg_sem = 1; static int toolatetochangeptcgsem = 0; +/* + * Kernel parameter "nptcg=" overrides max number of concurrent global TLB + * purges which is reported from either PAL or SAL PALO. + * + * We don't have sanity checking for nptcg value. It's the user's responsibility + * for valid nptcg value on the platform. Otherwise, kernel may hang in some + * cases. + */ +static int __init +set_nptcg(char *str) +{ + int value = 0; + + get_option(&str, &value); + setup_ptcg_sem(value, NPTCG_FROM_KERNEL_PARAMETER); + + return 1; +} + +__setup("nptcg=", set_nptcg); + /* * Maximum number of simultaneous ptc.g purges in the system can * be defined by PAL_VM_SUMMARY (in which case we should take @@ -126,13 +147,18 @@ static int toolatetochangeptcgsem = 0; * override table (in which case we should ignore the value from * PAL_VM_SUMMARY). * + * Kernel parameter "nptcg=" overrides maximum number of simultanesous ptc.g + * purges defined in either PAL_VM_SUMMARY or PAL override table. In this case, + * we should ignore the value from either PAL_VM_SUMMARY or PAL override table. + * * Complicating the logic here is the fact that num_possible_cpus() * isn't fully setup until we start bringing cpus online. */ void -setup_ptcg_sem(int max_purges, int from_palo) +setup_ptcg_sem(int max_purges, int nptcg_from) { - static int have_palo; + static int kp_override; + static int palo_override; static int firstcpu = 1; if (toolatetochangeptcgsem) { @@ -140,8 +166,18 @@ setup_ptcg_sem(int max_purges, int from_palo) return; } - if (from_palo) { - have_palo = 1; + if (nptcg_from == NPTCG_FROM_KERNEL_PARAMETER) { + kp_override = 1; + nptcg = max_purges; + goto resetsema; + } + if (kp_override) { + need_ptcg_sem = num_possible_cpus() > nptcg; + return; + } + + if (nptcg_from == NPTCG_FROM_PALO) { + palo_override = 1; /* In PALO max_purges == 0 really means it! */ if (max_purges == 0) @@ -153,7 +189,7 @@ setup_ptcg_sem(int max_purges, int from_palo) } goto resetsema; } - if (have_palo) { + if (palo_override) { if (nptcg != PALO_MAX_TLB_PURGES) need_ptcg_sem = (num_possible_cpus() > nptcg); return; diff --git a/include/asm-ia64/sal.h b/include/asm-ia64/sal.h index 3cd637a2c051..89594b442f83 100644 --- a/include/asm-ia64/sal.h +++ b/include/asm-ia64/sal.h @@ -896,6 +896,10 @@ struct palo_table { u8 reserved2[6]; }; +#define NPTCG_FROM_PAL 0 +#define NPTCG_FROM_PALO 1 +#define NPTCG_FROM_KERNEL_PARAMETER 2 + #endif /* __ASSEMBLY__ */ #endif /* _ASM_IA64_SAL_H */ -- cgit v1.2.3 From 40f6b36c6243462fb95d0343237331c423494b03 Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Sun, 24 Feb 2008 22:23:24 +0200 Subject: [SCSI] st: add option to use SILI in variable block reads Add new option MT_ST_SILI to enable setting the SILI bit in reads in variable block mode. If SILI is set, reading a block shorter than the byte count does not result in CHECK CONDITION. The length of the block is determined using the residual count from the HBA. Avoiding the REQUEST SENSE command for every block speeds up some real applications considerably. Signed-off-by: Kai Makisara Signed-off-by: James Bottomley --- Documentation/scsi/st.txt | 7 ++++++- drivers/scsi/st.c | 40 ++++++++++++++++++++++++++++++++++++---- drivers/scsi/st.h | 3 +++ drivers/scsi/st_options.h | 6 +++++- include/linux/mtio.h | 1 + 5 files changed, 51 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt index b7be95b5bd24..38f81188def0 100644 --- a/Documentation/scsi/st.txt +++ b/Documentation/scsi/st.txt @@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver. The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) -Last modified: Mon Mar 7 21:14:44 2005 by kai.makisara +Last modified: Thu Feb 21 21:54:16 2008 by kai.makisara BASICS @@ -372,6 +372,11 @@ MTSETDRVBUFFER MT_ST_SYSV sets the SYSV semantics (mode) MT_ST_NOWAIT enables immediate mode (i.e., don't wait for the command to finish) for some commands (e.g., rewind) + MT_ST_SILI enables setting the SILI bit in SCSI commands when + reading in variable block mode to enhance performance when + reading blocks shorter than the byte count; set this only + if you are sure that the drive supports SILI and the HBA + correctly returns transfer residuals MT_ST_DEBUGGING debugging (global; debugging must be compiled into the driver) MT_ST_SETBOOLEANS diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index 0a52d9d2da2c..a4361a8c6ac6 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -17,7 +17,7 @@ Last modified: 18-JAN-1998 Richard Gooch Devfs support */ -static const char *verstr = "20080221"; +static const char *verstr = "20080224"; #include @@ -183,6 +183,7 @@ static int modes_defined; static struct st_buffer *new_tape_buffer(int, int, int); static int enlarge_buffer(struct st_buffer *, int, int); +static void clear_buffer(struct st_buffer *); static void normalize_buffer(struct st_buffer *); static int append_to_buffer(const char __user *, struct st_buffer *, int); static int from_buffer(struct st_buffer *, char __user *, int); @@ -442,6 +443,7 @@ static void st_sleep_done(void *data, char *sense, int result, int resid) memcpy(SRpnt->sense, sense, SCSI_SENSE_BUFFERSIZE); (STp->buffer)->cmdstat.midlevel_result = SRpnt->result = result; + (STp->buffer)->cmdstat.residual = resid; DEB( STp->write_pending = 0; ) if (SRpnt->waiting) @@ -1159,6 +1161,7 @@ static int st_open(struct inode *inode, struct file *filp) goto err_out; } + (STp->buffer)->cleared = 0; (STp->buffer)->writing = 0; (STp->buffer)->syscall_result = 0; @@ -1432,8 +1435,14 @@ static int setup_buffering(struct scsi_tape *STp, const char __user *buf, if (STp->block_size) bufsize = STp->block_size > st_fixed_buffer_size ? STp->block_size : st_fixed_buffer_size; - else + else { bufsize = count; + /* Make sure that data from previous user is not leaked even if + HBA does not return correct residual */ + if (is_read && STp->sili && !STbp->cleared) + clear_buffer(STbp); + } + if (bufsize > STbp->buffer_size && !enlarge_buffer(STbp, bufsize, STp->restr_dma)) { printk(KERN_WARNING "%s: Can't allocate %d byte tape buffer.\n", @@ -1783,6 +1792,8 @@ static long read_tape(struct scsi_tape *STp, long count, memset(cmd, 0, MAX_COMMAND_SIZE); cmd[0] = READ_6; cmd[1] = (STp->block_size != 0); + if (!cmd[1] && STp->sili) + cmd[1] |= 2; cmd[2] = blks >> 16; cmd[3] = blks >> 8; cmd[4] = blks; @@ -1911,8 +1922,11 @@ static long read_tape(struct scsi_tape *STp, long count, } /* End of error handling */ - else /* Read successful */ + else { /* Read successful */ STbp->buffer_bytes = bytes; + if (STp->sili) /* In fixed block mode residual is always zero here */ + STbp->buffer_bytes -= STp->buffer->cmdstat.residual; + } if (STps->drv_block >= 0) { if (STp->block_size == 0) @@ -2090,7 +2104,8 @@ static void st_log_options(struct scsi_tape * STp, struct st_modedef * STm, char name, STm->defaults_for_writes, STp->omit_blklims, STp->can_partitions, STp->scsi2_logical); printk(KERN_INFO - "%s: sysv: %d nowait: %d\n", name, STm->sysv, STp->immediate); + "%s: sysv: %d nowait: %d sili: %d\n", name, STm->sysv, STp->immediate, + STp->sili); printk(KERN_INFO "%s: debugging: %d\n", name, debugging); } @@ -2133,6 +2148,7 @@ static int st_set_options(struct scsi_tape *STp, long options) STp->scsi2_logical = (options & MT_ST_SCSI2LOGICAL) != 0; STp->immediate = (options & MT_ST_NOWAIT) != 0; STm->sysv = (options & MT_ST_SYSV) != 0; + STp->sili = (options & MT_ST_SILI) != 0; DEB( debugging = (options & MT_ST_DEBUGGING) != 0; st_log_options(STp, STm, name); ) } else if (code == MT_ST_SETBOOLEANS || code == MT_ST_CLEARBOOLEANS) { @@ -2164,6 +2180,8 @@ static int st_set_options(struct scsi_tape *STp, long options) STp->immediate = value; if ((options & MT_ST_SYSV) != 0) STm->sysv = value; + if ((options & MT_ST_SILI) != 0) + STp->sili = value; DEB( if ((options & MT_ST_DEBUGGING) != 0) debugging = value; @@ -3655,6 +3673,8 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm STbuffer->frp_segs += 1; got += b_size; STbuffer->buffer_size = got; + if (STbuffer->cleared) + memset(page_address(STbuffer->frp[segs].page), 0, b_size); segs++; } STbuffer->b_data = page_address(STbuffer->frp[0].page); @@ -3663,6 +3683,17 @@ static int enlarge_buffer(struct st_buffer * STbuffer, int new_size, int need_dm } +/* Make sure that no data from previous user is in the internal buffer */ +static void clear_buffer(struct st_buffer * st_bp) +{ + int i; + + for (i=0; i < st_bp->frp_segs; i++) + memset(page_address(st_bp->frp[i].page), 0, st_bp->frp[i].length); + st_bp->cleared = 1; +} + + /* Release the extra buffer */ static void normalize_buffer(struct st_buffer * STbuffer) { @@ -3987,6 +4018,7 @@ static int st_probe(struct device *dev) tpnt->two_fm = ST_TWO_FM; tpnt->fast_mteom = ST_FAST_MTEOM; tpnt->scsi2_logical = ST_SCSI2LOGICAL; + tpnt->sili = ST_SILI; tpnt->immediate = ST_NOWAIT; tpnt->default_drvbuffer = 0xff; /* No forced buffering */ tpnt->partition = 0; diff --git a/drivers/scsi/st.h b/drivers/scsi/st.h index 5931726fcf93..b92712f95931 100644 --- a/drivers/scsi/st.h +++ b/drivers/scsi/st.h @@ -12,6 +12,7 @@ struct st_cmdstatus { int midlevel_result; struct scsi_sense_hdr sense_hdr; int have_sense; + int residual; u64 uremainder64; u8 flags; u8 remainder_valid; @@ -34,6 +35,7 @@ struct st_request { struct st_buffer { unsigned char dma; /* DMA-able buffer */ unsigned char do_dio; /* direct i/o set up? */ + unsigned char cleared; /* internal buffer cleared after open? */ int buffer_size; int buffer_blocks; int buffer_bytes; @@ -122,6 +124,7 @@ struct scsi_tape { unsigned char try_dio_now; /* try direct i/o before next close? */ unsigned char c_algo; /* compression algorithm */ unsigned char pos_unknown; /* after reset position unknown */ + unsigned char sili; /* use SILI when reading in variable b mode */ int tape_type; int long_timeout; /* timeout for commands known to take long time */ diff --git a/drivers/scsi/st_options.h b/drivers/scsi/st_options.h index b6b5c9c37677..d2f947935554 100644 --- a/drivers/scsi/st_options.h +++ b/drivers/scsi/st_options.h @@ -3,7 +3,7 @@ Copyright 1995-2003 Kai Makisara. - Last modified: Mon Apr 7 22:49:18 2003 by makisara + Last modified: Thu Feb 21 21:47:07 2008 by kai.makisara */ #ifndef _ST_OPTIONS_H @@ -94,6 +94,10 @@ The default is BSD semantics. */ #define ST_SYSV 0 +/* If ST_SILI is non-zero, the SILI bit is set when reading in variable block + mode and the block size is determined using the residual returned by the HBA. */ +#define ST_SILI 0 + /* Time to wait for the drive to become ready if blocking open */ #define ST_BLOCK_SECONDS 120 diff --git a/include/linux/mtio.h b/include/linux/mtio.h index 6f8d2d45a8fb..ef01d6aa5934 100644 --- a/include/linux/mtio.h +++ b/include/linux/mtio.h @@ -192,6 +192,7 @@ struct mtpos { #define MT_ST_SCSI2LOGICAL 0x800 #define MT_ST_SYSV 0x1000 #define MT_ST_NOWAIT 0x2000 +#define MT_ST_SILI 0x4000 /* The mode parameters to be controlled. Parameter chosen with bits 20-28 */ #define MT_ST_CLEAR_DEFAULT 0xfffff -- cgit v1.2.3 From b174be02f3634460ac215d249617dee5ae446ae1 Mon Sep 17 00:00:00 2001 From: Kai Makisara Date: Sun, 24 Feb 2008 22:29:12 +0200 Subject: [SCSI] st: show options currently set in sysfs Show the current binary tape driver and mode options is sysfs. A file (options) is created in each directory in /sys/class/scsi_tape. The files contain masks showing the options. The mask bit definitions are the same as used when setting the options using the MTSETDRVBUFFER function in the MTIOCTOP ioctl (defined in include/linux/mtio.h). For example: > cat /sys/class/scsi_tape/nst0/options 0x00000d07 [jejb: updated doc with correction from Randy Dunlap] Signed-off-by: Kai Makisara Signed-off-by: James Bottomley --- Documentation/scsi/st.txt | 7 ++++++- drivers/scsi/st.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/scsi/st.txt b/Documentation/scsi/st.txt index 38f81188def0..40752602c050 100644 --- a/Documentation/scsi/st.txt +++ b/Documentation/scsi/st.txt @@ -2,7 +2,7 @@ This file contains brief information about the SCSI tape driver. The driver is currently maintained by Kai Mäkisara (email Kai.Makisara@kolumbus.fi) -Last modified: Thu Feb 21 21:54:16 2008 by kai.makisara +Last modified: Sun Feb 24 21:59:07 2008 by kai.makisara BASICS @@ -133,6 +133,11 @@ the defaults set by the user. The value -1 means the default is not set. The file 'dev' contains the device numbers corresponding to this device. The links 'device' and 'driver' point to the SCSI device and driver entries. +Each directory also contains the entry 'options' which shows the currently +enabled driver and mode options. The value in the file is a bit mask where the +bit definitions are the same as those used with MTSETDRVBUFFER in setting the +options. + A link named 'tape' is made from the SCSI device directory to the class directory corresponding to the mode 0 auto-rewind device (e.g., st0). diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index a4361a8c6ac6..d204aad2e683 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c @@ -4365,6 +4365,46 @@ static ssize_t st_defcompression_show(struct class_device *class_dev, char *buf) CLASS_DEVICE_ATTR(default_compression, S_IRUGO, st_defcompression_show, NULL); +static ssize_t st_options_show(struct class_device *class_dev, char *buf) +{ + struct st_modedef *STm = (struct st_modedef *)class_get_devdata(class_dev); + struct scsi_tape *STp; + int i, j, options; + ssize_t l = 0; + + for (i=0; i < st_dev_max; i++) { + for (j=0; j < ST_NBR_MODES; j++) + if (&scsi_tapes[i]->modes[j] == STm) + break; + if (j < ST_NBR_MODES) + break; + } + if (i == st_dev_max) + return 0; /* should never happen */ + + STp = scsi_tapes[i]; + + options = STm->do_buffer_writes ? MT_ST_BUFFER_WRITES : 0; + options |= STm->do_async_writes ? MT_ST_ASYNC_WRITES : 0; + options |= STm->do_read_ahead ? MT_ST_READ_AHEAD : 0; + DEB( options |= debugging ? MT_ST_DEBUGGING : 0 ); + options |= STp->two_fm ? MT_ST_TWO_FM : 0; + options |= STp->fast_mteom ? MT_ST_FAST_MTEOM : 0; + options |= STm->defaults_for_writes ? MT_ST_DEF_WRITES : 0; + options |= STp->can_bsr ? MT_ST_CAN_BSR : 0; + options |= STp->omit_blklims ? MT_ST_NO_BLKLIMS : 0; + options |= STp->can_partitions ? MT_ST_CAN_PARTITIONS : 0; + options |= STp->scsi2_logical ? MT_ST_SCSI2LOGICAL : 0; + options |= STm->sysv ? MT_ST_SYSV : 0; + options |= STp->immediate ? MT_ST_NOWAIT : 0; + options |= STp->sili ? MT_ST_SILI : 0; + + l = snprintf(buf, PAGE_SIZE, "0x%08x\n", options); + return l; +} + +CLASS_DEVICE_ATTR(options, S_IRUGO, st_options_show, NULL); + static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) { int i, rew, error; @@ -4402,6 +4442,9 @@ static int do_create_class_files(struct scsi_tape *STp, int dev_num, int mode) error = class_device_create_file(st_class_member, &class_device_attr_default_compression); if (error) goto out; + error = class_device_create_file(st_class_member, + &class_device_attr_options); + if (error) goto out; if (mode == 0 && rew == 0) { error = sysfs_create_link(&STp->device->sdev_gendev.kobj, -- cgit v1.2.3 From 99971e70fdc1862e120f3319fc0a4dba8c728acf Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Tue, 15 Apr 2008 00:27:58 -0700 Subject: [WANPIPE]: Forgotten bits of Sangoma drivers removal. Robert P. J. Day spotted that my removal of the Sangoma drivers missed a few bits. Signed-off-by: Adrian Bunk Signed-off-by: David S. Miller --- Documentation/networking/00-INDEX | 2 - Documentation/networking/wan-router.txt | 621 -------------------------------- include/linux/Kbuild | 1 - include/linux/if_wanpipe.h | 124 ------- 4 files changed, 748 deletions(-) delete mode 100644 Documentation/networking/wan-router.txt delete mode 100644 include/linux/if_wanpipe.h (limited to 'Documentation') diff --git a/Documentation/networking/00-INDEX b/Documentation/networking/00-INDEX index c485ee028bd9..1634c6dcecae 100644 --- a/Documentation/networking/00-INDEX +++ b/Documentation/networking/00-INDEX @@ -100,8 +100,6 @@ tuntap.txt - TUN/TAP device driver, allowing user space Rx/Tx of packets. vortex.txt - info on using 3Com Vortex (3c590, 3c592, 3c595, 3c597) Ethernet cards. -wan-router.txt - - WAN router documentation wavelan.txt - AT&T GIS (nee NCR) WaveLAN card: An Ethernet-like radio transceiver x25.txt diff --git a/Documentation/networking/wan-router.txt b/Documentation/networking/wan-router.txt deleted file mode 100644 index bc2ab419a74a..000000000000 --- a/Documentation/networking/wan-router.txt +++ /dev/null @@ -1,621 +0,0 @@ ------------------------------------------------------------------------------- -Linux WAN Router Utilities Package ------------------------------------------------------------------------------- -Version 2.2.1 -Mar 28, 2001 -Author: Nenad Corbic -Copyright (c) 1995-2001 Sangoma Technologies Inc. ------------------------------------------------------------------------------- - -INTRODUCTION - -Wide Area Networks (WANs) are used to interconnect Local Area Networks (LANs) -and/or stand-alone hosts over vast distances with data transfer rates -significantly higher than those achievable with commonly used dial-up -connections. - -Usually an external device called `WAN router' sitting on your local network -or connected to your machine's serial port provides physical connection to -WAN. Although router's job may be as simple as taking your local network -traffic, converting it to WAN format and piping it through the WAN link, these -devices are notoriously expensive, with prices as much as 2 - 5 times higher -then the price of a typical PC box. - -Alternatively, considering robustness and multitasking capabilities of Linux, -an internal router can be built (most routers use some sort of stripped down -Unix-like operating system anyway). With a number of relatively inexpensive WAN -interface cards available on the market, a perfectly usable router can be -built for less than half a price of an external router. Yet a Linux box -acting as a router can still be used for other purposes, such as fire-walling, -running FTP, WWW or DNS server, etc. - -This kernel module introduces the notion of a WAN Link Driver (WLD) to Linux -operating system and provides generic hardware-independent services for such -drivers. Why can existing Linux network device interface not be used for -this purpose? Well, it can. However, there are a few key differences between -a typical network interface (e.g. Ethernet) and a WAN link. - -Many WAN protocols, such as X.25 and frame relay, allow for multiple logical -connections (known as `virtual circuits' in X.25 terminology) over a single -physical link. Each such virtual circuit may (and almost always does) lead -to a different geographical location and, therefore, different network. As a -result, it is the virtual circuit, not the physical link, that represents a -route and, therefore, a network interface in Linux terms. - -To further complicate things, virtual circuits are usually volatile in nature -(excluding so called `permanent' virtual circuits or PVCs). With almost no -time required to set up and tear down a virtual circuit, it is highly desirable -to implement on-demand connections in order to minimize network charges. So -unlike a typical network driver, the WAN driver must be able to handle multiple -network interfaces and cope as multiple virtual circuits come into existence -and go away dynamically. - -Last, but not least, WAN configuration is much more complex than that of say -Ethernet and may well amount to several dozens of parameters. Some of them -are "link-wide" while others are virtual circuit-specific. The same holds -true for WAN statistics which is by far more extensive and extremely useful -when troubleshooting WAN connections. Extending the ifconfig utility to suit -these needs may be possible, but does not seem quite reasonable. Therefore, a -WAN configuration utility and corresponding application programmer's interface -is needed for this purpose. - -Most of these problems are taken care of by this module. Its goal is to -provide a user with more-or-less standard look and feel for all WAN devices and -assist a WAN device driver writer by providing common services, such as: - - o User-level interface via /proc file system - o Centralized configuration - o Device management (setup, shutdown, etc.) - o Network interface management (dynamic creation/destruction) - o Protocol encapsulation/decapsulation - -To ba able to use the Linux WAN Router you will also need a WAN Tools package -available from - - ftp.sangoma.com/pub/linux/current_wanpipe/wanpipe-X.Y.Z.tgz - -where vX.Y.Z represent the wanpipe version number. - -For technical questions and/or comments please e-mail to ncorbic@sangoma.com. -For general inquiries please contact Sangoma Technologies Inc. by - - Hotline: 1-800-388-2475 (USA and Canada, toll free) - Phone: (905) 474-1990 ext: 106 - Fax: (905) 474-9223 - E-mail: dm@sangoma.com (David Mandelstam) - WWW: http://www.sangoma.com - - -INSTALLATION - -Please read the WanpipeForLinux.pdf manual on how to -install the WANPIPE tools and drivers properly. - - -After installing wanpipe package: /usr/local/wanrouter/doc. -On the ftp.sangoma.com : /linux/current_wanpipe/doc - - -COPYRIGHT AND LICENSING INFORMATION - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; either version 2, or (at your option) any later version. - -This program is distributed in the hope that it will be useful, but WITHOUT -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 675 Mass -Ave, Cambridge, MA 02139, USA. - - - -ACKNOWLEDGEMENTS - -This product is based on the WANPIPE(tm) Multiprotocol WAN Router developed -by Sangoma Technologies Inc. for Linux 2.0.x and 2.2.x. Success of the WANPIPE -together with the next major release of Linux kernel in summer 1996 commanded -adequate changes to the WANPIPE code to take full advantage of new Linux -features. - -Instead of continuing developing proprietary interface tied to Sangoma WAN -cards, we decided to separate all hardware-independent code into a separate -module and defined two levels of interfaces - one for user-level applications -and another for kernel-level WAN drivers. WANPIPE is now implemented as a -WAN driver compliant with the WAN Link Driver interface. Also a general -purpose WAN configuration utility and a set of shell scripts was developed to -support WAN router at the user level. - -Many useful ideas concerning hardware-independent interface implementation -were given by Mike McLagan and his implementation -of the Frame Relay router and drivers for Sangoma cards (dlci/sdla). - -With the new implementation of the APIs being incorporated into the WANPIPE, -a special thank goes to Alan Cox in providing insight into BSD sockets. - -Special thanks to all the WANPIPE users who performed field-testing, reported -bugs and made valuable comments and suggestions that help us to improve this -product. - - - -NEW IN THIS RELEASE - - o Updated the WANCFG utility - Calls the pppconfig to configure the PPPD - for async connections. - - o Added the PPPCONFIG utility - Used to configure the PPPD daemon for the - WANPIPE Async PPP and standard serial port. - The wancfg calls the pppconfig to configure - the pppd. - - o Fixed the PCI autodetect feature. - The SLOT 0 was used as an autodetect option - however, some high end PC's slot numbers start - from 0. - - o This release has been tested with the new backupd - daemon release. - - -PRODUCT COMPONENTS AND RELATED FILES - -/etc: (or user defined) - wanpipe1.conf default router configuration file - -/lib/modules/X.Y.Z/misc: - wanrouter.o router kernel loadable module - af_wanpipe.o wanpipe api socket module - -/lib/modules/X.Y.Z/net: - sdladrv.o Sangoma SDLA support module - wanpipe.o Sangoma WANPIPE(tm) driver module - -/proc/net/wanrouter - Config reads current router configuration - Status reads current router status - {name} reads WAN driver statistics - -/usr/sbin: - wanrouter wanrouter start-up script - wanconfig wanrouter configuration utility - sdladump WANPIPE adapter memory dump utility - fpipemon Monitor for Frame Relay - cpipemon Monitor for Cisco HDLC - ppipemon Monitor for PPP - xpipemon Monitor for X25 - wpkbdmon WANPIPE keyboard led monitor/debugger - -/usr/local/wanrouter: - README this file - COPYING GNU General Public License - Setup installation script - Filelist distribution definition file - wanrouter.rc meta-configuration file - (used by the Setup and wanrouter script) - -/usr/local/wanrouter/doc: - wanpipeForLinux.pdf WAN Router User's Manual - -/usr/local/wanrouter/patches: - wanrouter-v2213.gz patch for Linux kernels 2.2.11 up to 2.2.13. - wanrouter-v2214.gz patch for Linux kernel 2.2.14. - wanrouter-v2215.gz patch for Linux kernels 2.2.15 to 2.2.17. - wanrouter-v2218.gz patch for Linux kernels 2.2.18 and up. - wanrouter-v240.gz patch for Linux kernel 2.4.0. - wanrouter-v242.gz patch for Linux kernel 2.4.2 and up. - wanrouter-v2034.gz patch for Linux kernel 2.0.34 - wanrouter-v2036.gz patch for Linux kernel 2.0.36 and up. - -/usr/local/wanrouter/patches/kdrivers: - Sources of the latest WANPIPE device drivers. - These are used to UPGRADE the linux kernel to the newest - version if the kernel source has already been patched with - WANPIPE drivers. - -/usr/local/wanrouter/samples: - interface sample interface configuration file - wanpipe1.cpri CHDLC primary port - wanpipe2.csec CHDLC secondary port - wanpipe1.fr Frame Relay protocol - wanpipe1.ppp PPP protocol ) - wanpipe1.asy CHDLC ASYNC protocol - wanpipe1.x25 X25 protocol - wanpipe1.stty Sync TTY driver (Used by Kernel PPPD daemon) - wanpipe1.atty Async TTY driver (Used by Kernel PPPD daemon) - wanrouter.rc sample meta-configuration file - -/usr/local/wanrouter/util: - * wan-tools utilities source code - -/usr/local/wanrouter/api/x25: - * x25 api sample programs. -/usr/local/wanrouter/api/chdlc: - * chdlc api sample programs. -/usr/local/wanrouter/api/fr: - * fr api sample programs. -/usr/local/wanrouter/config/wancfg: - wancfg WANPIPE GUI configuration program. - Creates wanpipe#.conf files. -/usr/local/wanrouter/config/cfgft1: - cfgft1 GUI CSU/DSU configuration program. - -/usr/include/linux: - wanrouter.h router API definitions - wanpipe.h WANPIPE API definitions - sdladrv.h SDLA support module API definitions - sdlasfm.h SDLA firmware module definitions - if_wanpipe.h WANPIPE Socket definitions - sdlapci.h WANPIPE PCI definitions - - -/usr/src/linux/net/wanrouter: - * wanrouter source code - -/var/log: - wanrouter wanrouter start-up log (created by the Setup script) - -/var/lock: (or /var/lock/subsys for RedHat) - wanrouter wanrouter lock file (created by the Setup script) - -/usr/local/wanrouter/firmware: - fr514.sfm Frame relay firmware for Sangoma S508/S514 card - cdual514.sfm Dual Port Cisco HDLC firmware for Sangoma S508/S514 card - ppp514.sfm PPP Firmware for Sangoma S508 and S514 cards - x25_508.sfm X25 Firmware for Sangoma S508 card. - - -REVISION HISTORY - -1.0.0 December 31, 1996 Initial version - -1.0.1 January 30, 1997 Status and statistics can be read via /proc - filesystem entries. - -1.0.2 April 30, 1997 Added UDP management via monitors. - -1.0.3 June 3, 1997 UDP management for multiple boards using Frame - Relay and PPP - Enabled continuous transmission of Configure - Request Packet for PPP (for 508 only) - Connection Timeout for PPP changed from 900 to 0 - Flow Control Problem fixed for Frame Relay - -1.0.4 July 10, 1997 S508/FT1 monitoring capability in fpipemon and - ppipemon utilities. - Configurable TTL for UDP packets. - Multicast and Broadcast IP source addresses are - silently discarded. - -1.0.5 July 28, 1997 Configurable T391,T392,N391,N392,N393 for Frame - Relay in router.conf. - Configurable Memory Address through router.conf - for Frame Relay, PPP and X.25. (commenting this - out enables auto-detection). - Fixed freeing up received buffers using kfree() - for Frame Relay and X.25. - Protect sdla_peek() by calling save_flags(), - cli() and restore_flags(). - Changed number of Trace elements from 32 to 20 - Added DLCI specific data monitoring in FPIPEMON. -2.0.0 Nov 07, 1997 Implemented protection of RACE conditions by - critical flags for FRAME RELAY and PPP. - DLCI List interrupt mode implemented. - IPX support in FRAME RELAY and PPP. - IPX Server Support (MARS) - More driver specific stats included in FPIPEMON - and PIPEMON. - -2.0.1 Nov 28, 1997 Bug Fixes for version 2.0.0. - Protection of "enable_irq()" while - "disable_irq()" has been enabled from any other - routine (for Frame Relay, PPP and X25). - Added additional Stats for Fpipemon and Ppipemon - Improved Load Sharing for multiple boards - -2.0.2 Dec 09, 1997 Support for PAP and CHAP for ppp has been - implemented. - -2.0.3 Aug 15, 1998 New release supporting Cisco HDLC, CIR for Frame - relay, Dynamic IP assignment for PPP and Inverse - Arp support for Frame-relay. Man Pages are - included for better support and a new utility - for configuring FT1 cards. - -2.0.4 Dec 09, 1998 Dual Port support for Cisco HDLC. - Support for HDLC (LAPB) API. - Supports BiSync Streaming code for S502E - and S503 cards. - Support for Streaming HDLC API. - Provides a BSD socket interface for - creating applications using BiSync - streaming. - -2.0.5 Aug 04, 1999 CHDLC initialization bug fix. - PPP interrupt driven driver: - Fix to the PPP line hangup problem. - New PPP firmware - Added comments to the startup SYSTEM ERROR messages - Xpipemon debugging application for the X25 protocol - New USER_MANUAL.txt - Fixed the odd boundary 4byte writes to the board. - BiSync Streaming code has been taken out. - Available as a patch. - Streaming HDLC API has been taken out. - Available as a patch. - -2.0.6 Aug 17, 1999 Increased debugging in statup scripts - Fixed installation bugs from 2.0.5 - Kernel patch works for both 2.2.10 and 2.2.11 kernels. - There is no functional difference between the two packages - -2.0.7 Aug 26, 1999 o Merged X25API code into WANPIPE. - o Fixed a memory leak for X25API - o Updated the X25API code for 2.2.X kernels. - o Improved NEM handling. - -2.1.0 Oct 25, 1999 o New code for S514 PCI Card - o New CHDLC and Frame Relay drivers - o PPP and X25 are not supported in this release - -2.1.1 Nov 30, 1999 o PPP support for S514 PCI Cards - -2.1.3 Apr 06, 2000 o Socket based x25api - o Socket based chdlc api - o Socket based fr api - o Dual Port Receive only CHDLC support. - o Asynchronous CHDLC support (Secondary Port) - o cfgft1 GUI csu/dsu configurator - o wancfg GUI configuration file - configurator. - o Architectural directory changes. - -beta-2.1.4 Jul 2000 o Dynamic interface configuration: - Network interfaces reflect the state - of protocol layer. If the protocol becomes - disconnected, driver will bring down - the interface. Once the protocol reconnects - the interface will be brought up. - - Note: This option is turned off by default. - - o Dynamic wanrouter setup using 'wanconfig': - wanconfig utility can be used to - shutdown,restart,start or reconfigure - a virtual circuit dynamically. - - Frame Relay: Each DLCI can be: - created,stopped,restarted and reconfigured - dynamically using wanconfig. - - ex: wanconfig card wanpipe1 dev wp1_fr16 up - - o Wanrouter startup via command line arguments: - wanconfig also supports wanrouter startup via command line - arguments. Thus, there is no need to create a wanpipe#.conf - configuration file. - - o Socket based x25api update/bug fixes. - Added support for LCN numbers greater than 255. - Option to pass up modem messages. - Provided a PCI IRQ check, so a single S514 - card is guaranteed to have a non-sharing interrupt. - - o Fixes to the wancfg utility. - o New FT1 debugging support via *pipemon utilities. - o Frame Relay ARP support Enabled. - -beta3-2.1.4 Jul 2000 o X25 M_BIT Problem fix. - o Added the Multi-Port PPP - Updated utilities for the Multi-Port PPP. - -2.1.4 Aut 2000 - o In X25API: - Maximum packet an application can send - to the driver has been extended to 4096 bytes. - - Fixed the x25 startup bug. Enable - communications only after all interfaces - come up. HIGH SVC/PVC is used to calculate - the number of channels. - Enable protocol only after all interfaces - are enabled. - - o Added an extra state to the FT1 config, kernel module. - o Updated the pipemon debuggers. - - o Blocked the Multi-Port PPP from running on kernels - 2.2.16 or greater, due to syncppp kernel module - change. - -beta1-2.1.5 Nov 15 2000 - o Fixed the MultiPort PPP Support for kernels 2.2.16 and above. - 2.2.X kernels only - - o Secured the driver UDP debugging calls - - All illegal network debugging calls are reported to - the log. - - Defined a set of allowed commands, all other denied. - - o Cpipemon - - Added set FT1 commands to the cpipemon. Thus CSU/DSU - configuration can be performed using cpipemon. - All systems that cannot run cfgft1 GUI utility should - use cpipemon to configure the on board CSU/DSU. - - - o Keyboard Led Monitor/Debugger - - A new utility /usr/sbin/wpkbdmon uses keyboard leds - to convey operational statistic information of the - Sangoma WANPIPE cards. - NUM_LOCK = Line State (On=connected, Off=disconnected) - CAPS_LOCK = Tx data (On=transmitting, Off=no tx data) - SCROLL_LOCK = Rx data (On=receiving, Off=no rx data - - o Hardware probe on module load and dynamic device allocation - - During WANPIPE module load, all Sangoma cards are probed - and found information is printed in the /var/log/messages. - - If no cards are found, the module load fails. - - Appropriate number of devices are dynamically loaded - based on the number of Sangoma cards found. - - Note: The kernel configuration option - CONFIG_WANPIPE_CARDS has been taken out. - - o Fixed the Frame Relay and Chdlc network interfaces so they are - compatible with libpcap libraries. Meaning, tcpdump, snort, - ethereal, and all other packet sniffers and debuggers work on - all WANPIPE network interfaces. - - Set the network interface encoding type to ARPHRD_PPP. - This tell the sniffers that data obtained from the - network interface is in pure IP format. - Fix for 2.2.X kernels only. - - o True interface encoding option for Frame Relay and CHDLC - - The above fix sets the network interface encoding - type to ARPHRD_PPP, however some customers use - the encoding interface type to determine the - protocol running. Therefore, the TURE ENCODING - option will set the interface type back to the - original value. - - NOTE: If this option is used with Frame Relay and CHDLC - libpcap library support will be broken. - i.e. tcpdump will not work. - Fix for 2.2.x Kernels only. - - o Ethernet Bridgind over Frame Relay - - The Frame Relay bridging has been developed by - Kristian Hoffmann and Mark Wells. - - The Linux kernel bridge is used to send ethernet - data over the frame relay links. - For 2.2.X Kernels only. - - o Added extensive 2.0.X support. Most new features of - 2.1.5 for protocols Frame Relay, PPP and CHDLC are - supported under 2.0.X kernels. - -beta1-2.2.0 Dec 30 2000 - o Updated drivers for 2.4.X kernels. - o Updated drivers for SMP support. - o X25API is now able to share PCI interrupts. - o Took out a general polling routine that was used - only by X25API. - o Added appropriate locks to the dynamic reconfiguration - code. - o Fixed a bug in the keyboard debug monitor. - -beta2-2.2.0 Jan 8 2001 - o Patches for 2.4.0 kernel - o Patches for 2.2.18 kernel - o Minor updates to PPP and CHLDC drivers. - Note: No functional difference. - -beta3-2.2.9 Jan 10 2001 - o I missed the 2.2.18 kernel patches in beta2-2.2.0 - release. They are included in this release. - -Stable Release -2.2.0 Feb 01 2001 - o Bug fix in wancfg GUI configurator. - The edit function didn't work properly. - - -bata1-2.2.1 Feb 09 2001 - o WANPIPE TTY Driver emulation. - Two modes of operation Sync and Async. - Sync: Using the PPPD daemon, kernel SyncPPP layer - and the Wanpipe sync TTY driver: a PPP protocol - connection can be established via Sangoma adapter, over - a T1 leased line. - - The 2.4.0 kernel PPP layer supports MULTILINK - protocol, that can be used to bundle any number of Sangoma - adapters (T1 lines) into one, under a single IP address. - Thus, efficiently obtaining multiple T1 throughput. - - NOTE: The remote side must also implement MULTILINK PPP - protocol. - - Async:Using the PPPD daemon, kernel AsyncPPP layer - and the WANPIPE async TTY driver: a PPP protocol - connection can be established via Sangoma adapter and - a modem, over a telephone line. - - Thus, the WANPIPE async TTY driver simulates a serial - TTY driver that would normally be used to interface the - MODEM to the linux kernel. - - o WANPIPE PPP Backup Utility - This utility will monitor the state of the PPP T1 line. - In case of failure, a dial up connection will be established - via pppd daemon, ether via a serial tty driver (serial port), - or a WANPIPE async TTY driver (in case serial port is unavailable). - - Furthermore, while in dial up mode, the primary PPP T1 link - will be monitored for signs of life. - - If the PPP T1 link comes back to life, the dial up connection - will be shutdown and T1 line re-established. - - - o New Setup installation script. - Option to UPGRADE device drivers if the kernel source has - already been patched with WANPIPE. - - Option to COMPILE WANPIPE modules against the currently - running kernel, thus no need for manual kernel and module - re-compilation. - - o Updates and Bug Fixes to wancfg utility. - -bata2-2.2.1 Feb 20 2001 - - o Bug fixes to the CHDLC device drivers. - The driver had compilation problems under kernels - 2.2.14 or lower. - - o Bug fixes to the Setup installation script. - The device drivers compilation options didn't work - properly. - - o Update to the wpbackupd daemon. - Optimized the cross-over times, between the primary - link and the backup dialup. - -beta3-2.2.1 Mar 02 2001 - o Patches for 2.4.2 kernel. - - o Bug fixes to util/ make files. - o Bug fixes to the Setup installation script. - - o Took out the backupd support and made it into - as separate package. - -beta4-2.2.1 Mar 12 2001 - - o Fix to the Frame Relay Device driver. - IPSAC sends a packet of zero length - header to the frame relay driver. The - driver tries to push its own 2 byte header - into the packet, which causes the driver to - crash. - - o Fix the WANPIPE re-configuration code. - Bug was found by trying to run the cfgft1 while the - interface was already running. - - o Updates to cfgft1. - Writes a wanpipe#.cfgft1 configuration file - once the CSU/DSU is configured. This file can - holds the current CSU/DSU configuration. - - - ->>>>>> END OF README <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< - - diff --git a/include/linux/Kbuild b/include/linux/Kbuild index e56b739d8e23..b3d9ccde0c27 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild @@ -231,7 +231,6 @@ unifdef-y += if_pppol2tp.h unifdef-y += if_pppox.h unifdef-y += if_tr.h unifdef-y += if_vlan.h -unifdef-y += if_wanpipe.h unifdef-y += igmp.h unifdef-y += inet_diag.h unifdef-y += in.h diff --git a/include/linux/if_wanpipe.h b/include/linux/if_wanpipe.h deleted file mode 100644 index e594ca6069e5..000000000000 --- a/include/linux/if_wanpipe.h +++ /dev/null @@ -1,124 +0,0 @@ -/***************************************************************************** -* if_wanpipe.h Header file for the Sangoma AF_WANPIPE Socket -* -* Author: Nenad Corbic -* -* Copyright: (c) 2000 Sangoma Technologies Inc. -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version -* 2 of the License, or (at your option) any later version. -* ============================================================================ -* -* Jan 28, 2000 Nenad Corbic Initial Version -* -*****************************************************************************/ - -#ifndef __LINUX_IF_WAN_PACKET_H -#define __LINUX_IF_WAN_PACKET_H - -struct wan_sockaddr_ll -{ - unsigned short sll_family; - unsigned short sll_protocol; - int sll_ifindex; - unsigned short sll_hatype; - unsigned char sll_pkttype; - unsigned char sll_halen; - unsigned char sll_addr[8]; - unsigned char sll_device[14]; - unsigned char sll_card[14]; -}; - -typedef struct -{ - unsigned char free; - unsigned char state_sk; - int rcvbuf; - int sndbuf; - int rmem; - int wmem; - int sk_count; - unsigned char bound; - char name[14]; - unsigned char d_state; - unsigned char svc; - unsigned short lcn; - unsigned char mbox; - unsigned char cmd_busy; - unsigned char command; - unsigned poll; - unsigned poll_cnt; - int rblock; -} wan_debug_hdr_t; - -#define MAX_NUM_DEBUG 10 -#define X25_PROT 0x16 -#define PVC_PROT 0x17 - -typedef struct -{ - wan_debug_hdr_t debug[MAX_NUM_DEBUG]; -}wan_debug_t; - -#define SIOC_WANPIPE_GET_CALL_DATA (SIOCPROTOPRIVATE + 0) -#define SIOC_WANPIPE_SET_CALL_DATA (SIOCPROTOPRIVATE + 1) -#define SIOC_WANPIPE_ACCEPT_CALL (SIOCPROTOPRIVATE + 2) -#define SIOC_WANPIPE_CLEAR_CALL (SIOCPROTOPRIVATE + 3) -#define SIOC_WANPIPE_RESET_CALL (SIOCPROTOPRIVATE + 4) -#define SIOC_WANPIPE_DEBUG (SIOCPROTOPRIVATE + 5) -#define SIOC_WANPIPE_SET_NONBLOCK (SIOCPROTOPRIVATE + 6) -#define SIOC_WANPIPE_CHECK_TX (SIOCPROTOPRIVATE + 7) -#define SIOC_WANPIPE_SOCK_STATE (SIOCPROTOPRIVATE + 8) - -/* Packet types */ - -#define WAN_PACKET_HOST 0 /* To us */ -#define WAN_PACKET_BROADCAST 1 /* To all */ -#define WAN_PACKET_MULTICAST 2 /* To group */ -#define WAN_PACKET_OTHERHOST 3 /* To someone else */ -#define WAN_PACKET_OUTGOING 4 /* Outgoing of any type */ -/* These ones are invisible by user level */ -#define WAN_PACKET_LOOPBACK 5 /* MC/BRD frame looped back */ -#define WAN_PACKET_FASTROUTE 6 /* Fastrouted frame */ - - -/* X25 specific */ -#define WAN_PACKET_DATA 7 -#define WAN_PACKET_CMD 8 -#define WAN_PACKET_ASYNC 9 -#define WAN_PACKET_ERR 10 - -/* Packet socket options */ - -#define WAN_PACKET_ADD_MEMBERSHIP 1 -#define WAN_PACKET_DROP_MEMBERSHIP 2 - -#define WAN_PACKET_MR_MULTICAST 0 -#define WAN_PACKET_MR_PROMISC 1 -#define WAN_PACKET_MR_ALLMULTI 2 - -#ifdef __KERNEL__ - -/* Private wanpipe socket structures. */ -struct wanpipe_opt -{ - void *mbox; /* Mail box */ - void *card; /* Card bouded to */ - struct net_device *dev; /* Bounded device */ - unsigned short lcn; /* Binded LCN */ - unsigned char svc; /* 0=pvc, 1=svc */ - unsigned char timer; /* flag for delayed transmit*/ - struct timer_list tx_timer; - unsigned poll_cnt; - unsigned char force; /* Used to force sock release */ - atomic_t packet_sent; - unsigned short num; -}; - -#define wp_sk(__sk) ((struct wanpipe_opt *)(__sk)->sk_protinfo) - -#endif - -#endif -- cgit v1.2.3 From f5412c4980a9fbf9540078577747d7e098829e75 Mon Sep 17 00:00:00 2001 From: Dale Farnsworth Date: Tue, 8 Apr 2008 08:12:07 +1000 Subject: [POWERPC] Document the mv64x60 device tree bindings Add the device tree bindings for the Marvell mv64x60 series of system controller chips in booting-without-of.text. Signed-off-by: Dale Farnsworth Acked-by: Mark A. Greer Signed-off-by: Paul Mackerras --- Documentation/powerpc/booting-without-of.txt | 548 ++++++++++++++++++++++++++- 1 file changed, 545 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 1df9d4cfc0e6..2aafda9254f0 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -59,7 +59,30 @@ Table of Contents p) Freescale Synchronous Serial Interface q) USB EHCI controllers - VII - Specifying interrupt information for devices + VII - Marvell Discovery mv64[345]6x System Controller chips + 1) The /system-controller node + 2) Child nodes of /system-controller + a) Marvell Discovery MDIO bus + b) Marvell Discovery ethernet controller + c) Marvell Discovery PHY nodes + d) Marvell Discovery SDMA nodes + e) Marvell Discovery BRG nodes + f) Marvell Discovery CUNIT nodes + g) Marvell Discovery MPSCROUTING nodes + h) Marvell Discovery MPSCINTR nodes + i) Marvell Discovery MPSC nodes + j) Marvell Discovery Watch Dog Timer nodes + k) Marvell Discovery I2C nodes + l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes + m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes + n) Marvell Discovery GPP (General Purpose Pins) nodes + o) Marvell Discovery PCI host bridge node + p) Marvell Discovery CPU Error nodes + q) Marvell Discovery SRAM Controller nodes + r) Marvell Discovery PCI Error Handler nodes + s) Marvell Discovery Memory Controller nodes + + VIII - Specifying interrupt information for devices 1) interrupts property 2) interrupt-parent property 3) OpenPIC Interrupt Controllers @@ -2801,9 +2824,528 @@ platforms are moved over to use the flattened-device-tree model. }; - More devices will be defined as this spec matures. +VII - Marvell Discovery mv64[345]6x System Controller chips +=========================================================== -VII - Specifying interrupt information for devices +The Marvell mv64[345]60 series of system controller chips contain +many of the peripherals needed to implement a complete computer +system. In this section, we define device tree nodes to describe +the system controller chip itself and each of the peripherals +which it contains. Compatible string values for each node are +prefixed with the string "marvell,", for Marvell Technology Group Ltd. + +1) The /system-controller node + + This node is used to represent the system-controller and must be + present when the system uses a system contller chip. The top-level + system-controller node contains information that is global to all + devices within the system controller chip. The node name begins + with "system-controller" followed by the unit address, which is + the base address of the memory-mapped register set for the system + controller chip. + + Required properties: + + - ranges : Describes the translation of system controller addresses + for memory mapped registers. + - clock-frequency: Contains the main clock frequency for the system + controller chip. + - reg : This property defines the address and size of the + memory-mapped registers contained within the system controller + chip. The address specified in the "reg" property should match + the unit address of the system-controller node. + - #address-cells : Address representation for system controller + devices. This field represents the number of cells needed to + represent the address of the memory-mapped registers of devices + within the system controller chip. + - #size-cells : Size representation for for the memory-mapped + registers within the system controller chip. + - #interrupt-cells : Defines the width of cells used to represent + interrupts. + + Optional properties: + + - model : The specific model of the system controller chip. Such + as, "mv64360", "mv64460", or "mv64560". + - compatible : A string identifying the compatibility identifiers + of the system controller chip. + + The system-controller node contains child nodes for each system + controller device that the platform uses. Nodes should not be created + for devices which exist on the system controller chip but are not used + + Example Marvell Discovery mv64360 system-controller node: + + system-controller@f1000000 { /* Marvell Discovery mv64360 */ + #address-cells = <1>; + #size-cells = <1>; + model = "mv64360"; /* Default */ + compatible = "marvell,mv64360"; + clock-frequency = <133333333>; + reg = <0xf1000000 0x10000>; + virtual-reg = <0xf1000000>; + ranges = <0x88000000 0x88000000 0x1000000 /* PCI 0 I/O Space */ + 0x80000000 0x80000000 0x8000000 /* PCI 0 MEM Space */ + 0xa0000000 0xa0000000 0x4000000 /* User FLASH */ + 0x00000000 0xf1000000 0x0010000 /* Bridge's regs */ + 0xf2000000 0xf2000000 0x0040000>;/* Integrated SRAM */ + + [ child node definitions... ] + } + +2) Child nodes of /system-controller + + a) Marvell Discovery MDIO bus + + The MDIO is a bus to which the PHY devices are connected. For each + device that exists on this bus, a child node should be created. See + the definition of the PHY node below for an example of how to define + a PHY. + + Required properties: + - #address-cells : Should be <1> + - #size-cells : Should be <0> + - device_type : Should be "mdio" + - compatible : Should be "marvell,mv64360-mdio" + + Example: + + mdio { + #address-cells = <1>; + #size-cells = <0>; + device_type = "mdio"; + compatible = "marvell,mv64360-mdio"; + + ethernet-phy@0 { + ...... + }; + }; + + + b) Marvell Discovery ethernet controller + + The Discover ethernet controller is described with two levels + of nodes. The first level describes an ethernet silicon block + and the second level describes up to 3 ethernet nodes within + that block. The reason for the multiple levels is that the + registers for the node are interleaved within a single set + of registers. The "ethernet-block" level describes the + shared register set, and the "ethernet" nodes describe ethernet + port-specific properties. + + Ethernet block node + + Required properties: + - #address-cells : <1> + - #size-cells : <0> + - compatible : "marvell,mv64360-eth-block" + - reg : Offset and length of the register set for this block + + Example Discovery Ethernet block node: + ethernet-block@2000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "marvell,mv64360-eth-block"; + reg = <0x2000 0x2000>; + ethernet@0 { + ....... + }; + }; + + Ethernet port node + + Required properties: + - device_type : Should be "network". + - compatible : Should be "marvell,mv64360-eth". + - reg : Should be <0>, <1>, or <2>, according to which registers + within the silicon block the device uses. + - interrupts : where a is the interrupt number for the port. + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + - phy : the phandle for the PHY connected to this ethernet + controller. + - local-mac-address : 6 bytes, MAC address + + Example Discovery Ethernet port node: + ethernet@0 { + device_type = "network"; + compatible = "marvell,mv64360-eth"; + reg = <0>; + interrupts = <32>; + interrupt-parent = <&PIC>; + phy = <&PHY0>; + local-mac-address = [ 00 00 00 00 00 00 ]; + }; + + + + c) Marvell Discovery PHY nodes + + Required properties: + - device_type : Should be "ethernet-phy" + - interrupts : where a is the interrupt number for this phy. + - interrupt-parent : the phandle for the interrupt controller that + services interrupts for this device. + - reg : The ID number for the phy, usually a small integer + + Example Discovery PHY node: + ethernet-phy@1 { + device_type = "ethernet-phy"; + compatible = "broadcom,bcm5421"; + interrupts = <76>; /* GPP 12 */ + interrupt-parent = <&PIC>; + reg = <1>; + }; + + + d) Marvell Discovery SDMA nodes + + Represent DMA hardware associated with the MPSC (multiprotocol + serial controllers). + + Required properties: + - compatible : "marvell,mv64360-sdma" + - reg : Offset and length of the register set for this device + - interrupts : where a is the interrupt number for the DMA + device. + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery SDMA node: + sdma@4000 { + compatible = "marvell,mv64360-sdma"; + reg = <0x4000 0xc18>; + virtual-reg = <0xf1004000>; + interrupts = <36>; + interrupt-parent = <&PIC>; + }; + + + e) Marvell Discovery BRG nodes + + Represent baud rate generator hardware associated with the MPSC + (multiprotocol serial controllers). + + Required properties: + - compatible : "marvell,mv64360-brg" + - reg : Offset and length of the register set for this device + - clock-src : A value from 0 to 15 which selects the clock + source for the baud rate generator. This value corresponds + to the CLKS value in the BRGx configuration register. See + the mv64x60 User's Manual. + - clock-frequence : The frequency (in Hz) of the baud rate + generator's input clock. + - current-speed : The current speed setting (presumably by + firmware) of the baud rate generator. + + Example Discovery BRG node: + brg@b200 { + compatible = "marvell,mv64360-brg"; + reg = <0xb200 0x8>; + clock-src = <8>; + clock-frequency = <133333333>; + current-speed = <9600>; + }; + + + f) Marvell Discovery CUNIT nodes + + Represent the Serial Communications Unit device hardware. + + Required properties: + - reg : Offset and length of the register set for this device + + Example Discovery CUNIT node: + cunit@f200 { + reg = <0xf200 0x200>; + }; + + + g) Marvell Discovery MPSCROUTING nodes + + Represent the Discovery's MPSC routing hardware + + Required properties: + - reg : Offset and length of the register set for this device + + Example Discovery CUNIT node: + mpscrouting@b500 { + reg = <0xb400 0xc>; + }; + + + h) Marvell Discovery MPSCINTR nodes + + Represent the Discovery's MPSC DMA interrupt hardware registers + (SDMA cause and mask registers). + + Required properties: + - reg : Offset and length of the register set for this device + + Example Discovery MPSCINTR node: + mpsintr@b800 { + reg = <0xb800 0x100>; + }; + + + i) Marvell Discovery MPSC nodes + + Represent the Discovery's MPSC (Multiprotocol Serial Controller) + serial port. + + Required properties: + - device_type : "serial" + - compatible : "marvell,mv64360-mpsc" + - reg : Offset and length of the register set for this device + - sdma : the phandle for the SDMA node used by this port + - brg : the phandle for the BRG node used by this port + - cunit : the phandle for the CUNIT node used by this port + - mpscrouting : the phandle for the MPSCROUTING node used by this port + - mpscintr : the phandle for the MPSCINTR node used by this port + - cell-index : the hardware index of this cell in the MPSC core + - max_idle : value needed for MPSC CHR3 (Maximum Frame Length) + register + - interrupts : where a is the interrupt number for the MPSC. + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery MPSCINTR node: + mpsc@8000 { + device_type = "serial"; + compatible = "marvell,mv64360-mpsc"; + reg = <0x8000 0x38>; + virtual-reg = <0xf1008000>; + sdma = <&SDMA0>; + brg = <&BRG0>; + cunit = <&CUNIT>; + mpscrouting = <&MPSCROUTING>; + mpscintr = <&MPSCINTR>; + cell-index = <0>; + max_idle = <40>; + interrupts = <40>; + interrupt-parent = <&PIC>; + }; + + + j) Marvell Discovery Watch Dog Timer nodes + + Represent the Discovery's watchdog timer hardware + + Required properties: + - compatible : "marvell,mv64360-wdt" + - reg : Offset and length of the register set for this device + + Example Discovery Watch Dog Timer node: + wdt@b410 { + compatible = "marvell,mv64360-wdt"; + reg = <0xb410 0x8>; + }; + + + k) Marvell Discovery I2C nodes + + Represent the Discovery's I2C hardware + + Required properties: + - device_type : "i2c" + - compatible : "marvell,mv64360-i2c" + - reg : Offset and length of the register set for this device + - interrupts : where a is the interrupt number for the I2C. + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery I2C node: + compatible = "marvell,mv64360-i2c"; + reg = <0xc000 0x20>; + virtual-reg = <0xf100c000>; + interrupts = <37>; + interrupt-parent = <&PIC>; + }; + + + l) Marvell Discovery PIC (Programmable Interrupt Controller) nodes + + Represent the Discovery's PIC hardware + + Required properties: + - #interrupt-cells : <1> + - #address-cells : <0> + - compatible : "marvell,mv64360-pic" + - reg : Offset and length of the register set for this device + - interrupt-controller + + Example Discovery PIC node: + pic { + #interrupt-cells = <1>; + #address-cells = <0>; + compatible = "marvell,mv64360-pic"; + reg = <0x0 0x88>; + interrupt-controller; + }; + + + m) Marvell Discovery MPP (Multipurpose Pins) multiplexing nodes + + Represent the Discovery's MPP hardware + + Required properties: + - compatible : "marvell,mv64360-mpp" + - reg : Offset and length of the register set for this device + + Example Discovery MPP node: + mpp@f000 { + compatible = "marvell,mv64360-mpp"; + reg = <0xf000 0x10>; + }; + + + n) Marvell Discovery GPP (General Purpose Pins) nodes + + Represent the Discovery's GPP hardware + + Required properties: + - compatible : "marvell,mv64360-gpp" + - reg : Offset and length of the register set for this device + + Example Discovery GPP node: + gpp@f000 { + compatible = "marvell,mv64360-gpp"; + reg = <0xf100 0x20>; + }; + + + o) Marvell Discovery PCI host bridge node + + Represents the Discovery's PCI host bridge device. The properties + for this node conform to Rev 2.1 of the PCI Bus Binding to IEEE + 1275-1994. A typical value for the compatible property is + "marvell,mv64360-pci". + + Example Discovery PCI host bridge node + pci@80000000 { + #address-cells = <3>; + #size-cells = <2>; + #interrupt-cells = <1>; + device_type = "pci"; + compatible = "marvell,mv64360-pci"; + reg = <0xcf8 0x8>; + ranges = <0x01000000 0x0 0x0 + 0x88000000 0x0 0x01000000 + 0x02000000 0x0 0x80000000 + 0x80000000 0x0 0x08000000>; + bus-range = <0 255>; + clock-frequency = <66000000>; + interrupt-parent = <&PIC>; + interrupt-map-mask = <0xf800 0x0 0x0 0x7>; + interrupt-map = < + /* IDSEL 0x0a */ + 0x5000 0 0 1 &PIC 80 + 0x5000 0 0 2 &PIC 81 + 0x5000 0 0 3 &PIC 91 + 0x5000 0 0 4 &PIC 93 + + /* IDSEL 0x0b */ + 0x5800 0 0 1 &PIC 91 + 0x5800 0 0 2 &PIC 93 + 0x5800 0 0 3 &PIC 80 + 0x5800 0 0 4 &PIC 81 + + /* IDSEL 0x0c */ + 0x6000 0 0 1 &PIC 91 + 0x6000 0 0 2 &PIC 93 + 0x6000 0 0 3 &PIC 80 + 0x6000 0 0 4 &PIC 81 + + /* IDSEL 0x0d */ + 0x6800 0 0 1 &PIC 93 + 0x6800 0 0 2 &PIC 80 + 0x6800 0 0 3 &PIC 81 + 0x6800 0 0 4 &PIC 91 + >; + }; + + + p) Marvell Discovery CPU Error nodes + + Represent the Discovery's CPU error handler device. + + Required properties: + - compatible : "marvell,mv64360-cpu-error" + - reg : Offset and length of the register set for this device + - interrupts : the interrupt number for this device + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery CPU Error node: + cpu-error@0070 { + compatible = "marvell,mv64360-cpu-error"; + reg = <0x70 0x10 0x128 0x28>; + interrupts = <3>; + interrupt-parent = <&PIC>; + }; + + + q) Marvell Discovery SRAM Controller nodes + + Represent the Discovery's SRAM controller device. + + Required properties: + - compatible : "marvell,mv64360-sram-ctrl" + - reg : Offset and length of the register set for this device + - interrupts : the interrupt number for this device + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery SRAM Controller node: + sram-ctrl@0380 { + compatible = "marvell,mv64360-sram-ctrl"; + reg = <0x380 0x80>; + interrupts = <13>; + interrupt-parent = <&PIC>; + }; + + + r) Marvell Discovery PCI Error Handler nodes + + Represent the Discovery's PCI error handler device. + + Required properties: + - compatible : "marvell,mv64360-pci-error" + - reg : Offset and length of the register set for this device + - interrupts : the interrupt number for this device + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery PCI Error Handler node: + pci-error@1d40 { + compatible = "marvell,mv64360-pci-error"; + reg = <0x1d40 0x40 0xc28 0x4>; + interrupts = <12>; + interrupt-parent = <&PIC>; + }; + + + s) Marvell Discovery Memory Controller nodes + + Represent the Discovery's memory controller device. + + Required properties: + - compatible : "marvell,mv64360-mem-ctrl" + - reg : Offset and length of the register set for this device + - interrupts : the interrupt number for this device + - interrupt-parent : the phandle for the interrupt controller + that services interrupts for this device. + + Example Discovery Memory Controller node: + mem-ctrl@1400 { + compatible = "marvell,mv64360-mem-ctrl"; + reg = <0x1400 0x60>; + interrupts = <17>; + interrupt-parent = <&PIC>; + }; + + +VIII - Specifying interrupt information for devices =================================================== The device tree represents the busses and devices of a hardware -- cgit v1.2.3 From b7ce341585a51a6d65c7a77b6918132a3b360b81 Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 11 Apr 2008 23:06:36 +1000 Subject: [POWERPC] Implement support for the GPIO LIB API This implements support for the GPIO LIB API. Two calls are still unimplemented though: irq_to_gpio and gpio_to_irq. Signed-off-by: Anton Vorontsov Acked-by: Grant Likely Signed-off-by: Paul Mackerras --- Documentation/powerpc/booting-without-of.txt | 52 ++++++++++++++++++++++++++ arch/powerpc/Kconfig | 5 +++ include/asm-powerpc/gpio.h | 56 ++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+) create mode 100644 include/asm-powerpc/gpio.h (limited to 'Documentation') diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 2aafda9254f0..528b4822f451 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -88,6 +88,10 @@ Table of Contents 3) OpenPIC Interrupt Controllers 4) ISA Interrupt Controllers + VIII - Specifying GPIO information for devices + 1) gpios property + 2) gpio-controller nodes + Appendix A - Sample SOC node for MPC8540 @@ -3431,6 +3435,54 @@ encodings listed below: 2 = high to low edge sensitive type enabled 3 = low to high edge sensitive type enabled +VIII - Specifying GPIO information for devices +============================================== + +1) gpios property +----------------- + +Nodes that makes use of GPIOs should define them using `gpios' property, +format of which is: <&gpio-controller1-phandle gpio1-specifier + &gpio-controller2-phandle gpio2-specifier + 0 /* holes are permitted, means no GPIO 3 */ + &gpio-controller4-phandle gpio4-specifier + ...>; + +Note that gpio-specifier length is controller dependent. + +gpio-specifier may encode: bank, pin position inside the bank, +whether pin is open-drain and whether pin is logically inverted. + +Example of the node using GPIOs: + + node { + gpios = <&qe_pio_e 18 0>; + }; + +In this example gpio-specifier is "18 0" and encodes GPIO pin number, +and empty GPIO flags as accepted by the "qe_pio_e" gpio-controller. + +2) gpio-controller nodes +------------------------ + +Every GPIO controller node must have #gpio-cells property defined, +this information will be used to translate gpio-specifiers. + +Example of two SOC GPIO banks defined as gpio-controller nodes: + + qe_pio_a: gpio-controller@1400 { + #gpio-cells = <2>; + compatible = "fsl,qe-pario-bank-a", "fsl,qe-pario-bank"; + reg = <0x1400 0x18>; + gpio-controller; + }; + + qe_pio_e: gpio-controller@1460 { + #gpio-cells = <2>; + compatible = "fsl,qe-pario-bank-e", "fsl,qe-pario-bank"; + reg = <0x1460 0x18>; + gpio-controller; + }; Appendix A - Sample SOC node for MPC8540 ======================================== diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 1d4d19f6d6e1..c51b6bba5fce 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -81,6 +81,11 @@ config GENERIC_FIND_NEXT_BIT bool default y +config GENERIC_GPIO + bool + help + Generic GPIO API support + config ARCH_NO_VIRT_TO_BUS def_bool PPC64 diff --git a/include/asm-powerpc/gpio.h b/include/asm-powerpc/gpio.h new file mode 100644 index 000000000000..77ad3a890f30 --- /dev/null +++ b/include/asm-powerpc/gpio.h @@ -0,0 +1,56 @@ +/* + * Generic GPIO API implementation for PowerPC. + * + * Copyright (c) 2007-2008 MontaVista Software, Inc. + * + * Author: Anton Vorontsov + * + * 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. + */ + +#ifndef __ASM_POWERPC_GPIO_H +#define __ASM_POWERPC_GPIO_H + +#include +#include + +#ifdef CONFIG_HAVE_GPIO_LIB + +/* + * We don't (yet) implement inlined/rapid versions for on-chip gpios. + * Just call gpiolib. + */ +static inline int gpio_get_value(unsigned int gpio) +{ + return __gpio_get_value(gpio); +} + +static inline void gpio_set_value(unsigned int gpio, int value) +{ + __gpio_set_value(gpio, value); +} + +static inline int gpio_cansleep(unsigned int gpio) +{ + return __gpio_cansleep(gpio); +} + +/* + * Not implemented, yet. + */ +static inline int gpio_to_irq(unsigned int gpio) +{ + return -ENOSYS; +} + +static inline int irq_to_gpio(unsigned int irq) +{ + return -EINVAL; +} + +#endif /* CONFIG_HAVE_GPIO_LIB */ + +#endif /* __ASM_POWERPC_GPIO_H */ -- cgit v1.2.3 From 9637c3f318374e2fcc37e354f9782a705b517387 Mon Sep 17 00:00:00 2001 From: Michael Holzheu Date: Thu, 17 Apr 2008 07:46:18 +0200 Subject: [S390] Add debug_register_mode() function to debug feature API The new function supports setting of permissions for the debugfs files created by the debug feature. In addition to that, the function provides uid and gid as parameters for future use. Currently only root is allowed for uid and gid. Signed-off-by: Michael Holzheu Signed-off-by: Martin Schwidefsky Signed-off-by: Heiko Carstens --- Documentation/s390/s390dbf.txt | 21 +++++++++++++++++ arch/s390/kernel/debug.c | 51 +++++++++++++++++++++++++++++++----------- include/asm-s390/debug.h | 5 +++++ 3 files changed, 64 insertions(+), 13 deletions(-) (limited to 'Documentation') diff --git a/Documentation/s390/s390dbf.txt b/Documentation/s390/s390dbf.txt index 0eb7c58916de..e05420973698 100644 --- a/Documentation/s390/s390dbf.txt +++ b/Documentation/s390/s390dbf.txt @@ -115,6 +115,27 @@ Return Value: Handle for generated debug area Description: Allocates memory for a debug log Must not be called within an interrupt handler +---------------------------------------------------------------------------- +debug_info_t *debug_register_mode(char *name, int pages, int nr_areas, + int buf_size, mode_t mode, uid_t uid, + gid_t gid); + +Parameter: name: Name of debug log (e.g. used for debugfs entry) + pages: Number of pages, which will be allocated per area + nr_areas: Number of debug areas + buf_size: Size of data area in each debug entry + mode: File mode for debugfs files. E.g. S_IRWXUGO + uid: User ID for debugfs files. Currently only 0 is + supported. + gid: Group ID for debugfs files. Currently only 0 is + supported. + +Return Value: Handle for generated debug area + NULL if register failed + +Description: Allocates memory for a debug log + Must not be called within an interrupt handler + --------------------------------------------------------------------------- void debug_unregister (debug_info_t * id); diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c index 1b2f5ce45320..95a46bc008b7 100644 --- a/arch/s390/kernel/debug.c +++ b/arch/s390/kernel/debug.c @@ -73,7 +73,7 @@ static ssize_t debug_input(struct file *file, const char __user *user_buf, static int debug_open(struct inode *inode, struct file *file); static int debug_close(struct inode *inode, struct file *file); static debug_info_t* debug_info_create(char *name, int pages_per_area, - int nr_areas, int buf_size); + int nr_areas, int buf_size, mode_t mode); static void debug_info_get(debug_info_t *); static void debug_info_put(debug_info_t *); static int debug_prolog_level_fn(debug_info_t * id, @@ -327,7 +327,8 @@ debug_info_free(debug_info_t* db_info){ */ static debug_info_t* -debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size) +debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size, + mode_t mode) { debug_info_t* rc; @@ -336,6 +337,8 @@ debug_info_create(char *name, int pages_per_area, int nr_areas, int buf_size) if(!rc) goto out; + rc->mode = mode & ~S_IFMT; + /* create root directory */ rc->debugfs_root_entry = debugfs_create_dir(rc->name, debug_debugfs_root_entry); @@ -676,23 +679,30 @@ debug_close(struct inode *inode, struct file *file) } /* - * debug_register: - * - creates and initializes debug area for the caller - * - returns handle for debug area + * debug_register_mode: + * - Creates and initializes debug area for the caller + * The mode parameter allows to specify access rights for the s390dbf files + * - Returns handle for debug area */ -debug_info_t* -debug_register (char *name, int pages_per_area, int nr_areas, int buf_size) +debug_info_t *debug_register_mode(char *name, int pages_per_area, int nr_areas, + int buf_size, mode_t mode, uid_t uid, + gid_t gid) { debug_info_t *rc = NULL; + /* Since debugfs currently does not support uid/gid other than root, */ + /* we do not allow gid/uid != 0 until we get support for that. */ + if ((uid != 0) || (gid != 0)) + printk(KERN_WARNING "debug: Warning - Currently only uid/gid " + "= 0 are supported. Using root as owner now!"); if (!initialized) BUG(); mutex_lock(&debug_mutex); /* create new debug_info */ - rc = debug_info_create(name, pages_per_area, nr_areas, buf_size); + rc = debug_info_create(name, pages_per_area, nr_areas, buf_size, mode); if(!rc) goto out; debug_register_view(rc, &debug_level_view); @@ -705,6 +715,20 @@ out: mutex_unlock(&debug_mutex); return rc; } +EXPORT_SYMBOL(debug_register_mode); + +/* + * debug_register: + * - creates and initializes debug area for the caller + * - returns handle for debug area + */ + +debug_info_t *debug_register(char *name, int pages_per_area, int nr_areas, + int buf_size) +{ + return debug_register_mode(name, pages_per_area, nr_areas, buf_size, + S_IRUSR | S_IWUSR, 0, 0); +} /* * debug_unregister: @@ -1073,15 +1097,16 @@ debug_register_view(debug_info_t * id, struct debug_view *view) int rc = 0; int i; unsigned long flags; - mode_t mode = S_IFREG; + mode_t mode; struct dentry *pde; if (!id) goto out; - if (view->prolog_proc || view->format_proc || view->header_proc) - mode |= S_IRUSR; - if (view->input_proc) - mode |= S_IWUSR; + mode = (id->mode | S_IFREG) & ~S_IXUGO; + if (!(view->prolog_proc || view->format_proc || view->header_proc)) + mode &= ~(S_IRUSR | S_IRGRP | S_IROTH); + if (!view->input_proc) + mode &= ~(S_IWUSR | S_IWGRP | S_IWOTH); pde = debugfs_create_file(view->name, mode, id->debugfs_root_entry, id , &debug_file_ops); if (!pde){ diff --git a/include/asm-s390/debug.h b/include/asm-s390/debug.h index c00dd2b3dc50..335baf4fc64f 100644 --- a/include/asm-s390/debug.h +++ b/include/asm-s390/debug.h @@ -73,6 +73,7 @@ typedef struct debug_info { struct dentry* debugfs_entries[DEBUG_MAX_VIEWS]; struct debug_view* views[DEBUG_MAX_VIEWS]; char name[DEBUG_MAX_NAME_LEN]; + mode_t mode; } debug_info_t; typedef int (debug_header_proc_t) (debug_info_t* id, @@ -122,6 +123,10 @@ debug_entry_t* debug_exception_common(debug_info_t* id, int level, debug_info_t* debug_register(char* name, int pages, int nr_areas, int buf_size); +debug_info_t *debug_register_mode(char *name, int pages, int nr_areas, + int buf_size, mode_t mode, uid_t uid, + gid_t gid); + void debug_unregister(debug_info_t* id); void debug_set_level(debug_info_t* id, int new_level); -- cgit v1.2.3 From 56626f335b76eecd79d07fb21d0e625eb4aa52da Mon Sep 17 00:00:00 2001 From: Anton Vorontsov Date: Fri, 11 Apr 2008 20:06:54 +0400 Subject: [POWERPC] QE: UCC nodes cleanup - get rid of `model = "UCC"' in the ucc nodes It isn't used anywhere, so remove it. If we'll ever need something like this, we'll use compatible property instead. - replace last occurrences of device-id with cell-index. Drivers are modified for backward compatibility's sake. Signed-off-by: Anton Vorontsov Acked-by: Timur Tabi Signed-off-by: Kumar Gala --- Documentation/powerpc/booting-without-of.txt | 6 ++---- arch/powerpc/boot/dts/mpc832x_mds.dts | 7 +------ arch/powerpc/boot/dts/mpc832x_rdb.dts | 4 ---- arch/powerpc/boot/dts/mpc836x_mds.dts | 4 ---- arch/powerpc/boot/dts/mpc8568mds.dts | 4 ---- drivers/net/ucc_geth.c | 8 +++++++- drivers/net/ucc_geth_mii.c | 11 ++++++++--- drivers/serial/ucc_uart.c | 16 ++++++++++++---- 8 files changed, 30 insertions(+), 30 deletions(-) (limited to 'Documentation') diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 528b4822f451..4cc780024e6c 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -1645,8 +1645,7 @@ platforms are moved over to use the flattened-device-tree model. - device_type : should be "network", "hldc", "uart", "transparent" "bisync", "atm", or "serial". - compatible : could be "ucc_geth" or "fsl_atm" and so on. - - model : should be "UCC". - - device-id : the ucc number(1-8), corresponding to UCCx in UM. + - cell-index : the ucc number(1-8), corresponding to UCCx in UM. - reg : Offset and length of the register set for the device - interrupts : where a is the interrupt number and b is a field that represents an encoding of the sense and level @@ -1699,8 +1698,7 @@ platforms are moved over to use the flattened-device-tree model. ucc@2000 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; - device-id = <1>; + cell-index = <1>; reg = <2000 200>; interrupts = ; interrupt-parent = <700>; diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 9bb408371bcd..539e02fb3526 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts @@ -255,9 +255,7 @@ enet0: ucc@2200 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; cell-index = <3>; - device-id = <3>; reg = <0x2200 0x200>; interrupts = <34>; interrupt-parent = <&qeic>; @@ -271,9 +269,7 @@ enet1: ucc@3200 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; cell-index = <4>; - device-id = <4>; reg = <0x3200 0x200>; interrupts = <35>; interrupt-parent = <&qeic>; @@ -287,8 +283,7 @@ ucc@2400 { device_type = "serial"; compatible = "ucc_uart"; - model = "UCC"; - device-id = <5>; /* The UCC number, 1-7*/ + cell-index = <5>; /* The UCC number, 1-7*/ port-number = <0>; /* Which ttyQEx device */ soft-uart; /* We need Soft-UART */ reg = <0x2400 0x200>; diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts index 94f93d209de8..179c81c6a7ac 100644 --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts @@ -208,9 +208,7 @@ enet0: ucc@3000 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; cell-index = <2>; - device-id = <2>; reg = <0x3000 0x200>; interrupts = <33>; interrupt-parent = <&qeic>; @@ -224,9 +222,7 @@ enet1: ucc@2200 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; cell-index = <3>; - device-id = <3>; reg = <0x2200 0x200>; interrupts = <34>; interrupt-parent = <&qeic>; diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 55f03e8dc97f..8160ff24e87e 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts @@ -257,9 +257,7 @@ enet0: ucc@2000 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; cell-index = <1>; - device-id = <1>; reg = <0x2000 0x200>; interrupts = <32>; interrupt-parent = <&qeic>; @@ -274,9 +272,7 @@ enet1: ucc@3000 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; cell-index = <2>; - device-id = <2>; reg = <0x3000 0x200>; interrupts = <33>; interrupt-parent = <&qeic>; diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts index 97bc048f2158..df4b5e89d7e4 100644 --- a/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/arch/powerpc/boot/dts/mpc8568mds.dts @@ -324,9 +324,7 @@ enet2: ucc@2000 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; cell-index = <1>; - device-id = <1>; reg = <2000 200>; interrupts = <20>; interrupt-parent = <&qeic>; @@ -341,9 +339,7 @@ enet3: ucc@3000 { device_type = "network"; compatible = "ucc_geth"; - model = "UCC"; cell-index = <2>; - device-id = <2>; reg = <3000 200>; interrupts = <21>; interrupt-parent = <&qeic>; diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c index 8cc316653a39..ed84182c6828 100644 --- a/drivers/net/ucc_geth.c +++ b/drivers/net/ucc_geth.c @@ -3852,7 +3852,13 @@ static int ucc_geth_probe(struct of_device* ofdev, const struct of_device_id *ma ugeth_vdbg("%s: IN", __FUNCTION__); - prop = of_get_property(np, "device-id", NULL); + prop = of_get_property(np, "cell-index", NULL); + if (!prop) { + prop = of_get_property(np, "device-id", NULL); + if (!prop) + return -ENODEV; + } + ucc_num = *prop - 1; if ((ucc_num < 0) || (ucc_num > 7)) return -ENODEV; diff --git a/drivers/net/ucc_geth_mii.c b/drivers/net/ucc_geth_mii.c index c69e654d539f..8a48ddb1e866 100644 --- a/drivers/net/ucc_geth_mii.c +++ b/drivers/net/ucc_geth_mii.c @@ -203,9 +203,14 @@ static int uec_mdio_probe(struct of_device *ofdev, const struct of_device_id *ma if ((res.start >= tempres.start) && (res.end <= tempres.end)) { /* set this UCC to be the MII master */ - const u32 *id = of_get_property(tempnp, "device-id", NULL); - if (id == NULL) - goto bus_register_fail; + const u32 *id; + + id = of_get_property(tempnp, "cell-index", NULL); + if (!id) { + id = of_get_property(tempnp, "device-id", NULL); + if (!id) + goto bus_register_fail; + } ucc_set_qe_mux_mii_mng(*id - 1); diff --git a/drivers/serial/ucc_uart.c b/drivers/serial/ucc_uart.c index e0994f061001..5e4310ccd591 100644 --- a/drivers/serial/ucc_uart.c +++ b/drivers/serial/ucc_uart.c @@ -1270,10 +1270,18 @@ static int ucc_uart_probe(struct of_device *ofdev, /* Get the UCC number (device ID) */ /* UCCs are numbered 1-7 */ - iprop = of_get_property(np, "device-id", NULL); - if (!iprop || (*iprop < 1) || (*iprop > UCC_MAX_NUM)) { - dev_err(&ofdev->dev, - "missing or invalid UCC specified in device tree\n"); + iprop = of_get_property(np, "cell-index", NULL); + if (!iprop) { + iprop = of_get_property(np, "device-id", NULL); + if (!iprop) { + dev_err(&ofdev->dev, "UCC is unspecified in " + "device tree\n"); + return -EINVAL; + } + } + + if ((*iprop < 1) || (*iprop > UCC_MAX_NUM)) { + dev_err(&ofdev->dev, "no support for UCC%u\n", *iprop); kfree(qe_port); return -ENODEV; } -- cgit v1.2.3 From f4988927a257791d372dddeda8eda8521bf6cb00 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Fri, 8 Feb 2008 12:13:08 +0200 Subject: Documentation: add UBI sysfs ABI docs Signed-off-by: Artem Bityutskiy Acked-by: Greg KH --- Documentation/ABI/stable/sysfs-class-ubi | 212 +++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 Documentation/ABI/stable/sysfs-class-ubi (limited to 'Documentation') diff --git a/Documentation/ABI/stable/sysfs-class-ubi b/Documentation/ABI/stable/sysfs-class-ubi new file mode 100644 index 000000000000..18d471d9faea --- /dev/null +++ b/Documentation/ABI/stable/sysfs-class-ubi @@ -0,0 +1,212 @@ +What: /sys/class/ubi/ +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + The ubi/ class sub-directory belongs to the UBI subsystem and + provides general UBI information, per-UBI device information + and per-UBI volume information. + +What: /sys/class/ubi/version +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + This file contains version of the latest supported UBI on-media + format. Currently it is 1, and there is no plan to change this. + However, if in the future UBI needs on-flash format changes + which cannot be done in a compatible manner, a new format + version will be added. So this is a mechanism for possible + future backward-compatible (but forward-incompatible) + improvements. + +What: /sys/class/ubiX/ +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + The /sys/class/ubi0, /sys/class/ubi1, etc directories describe + UBI devices (UBI device 0, 1, etc). They contain general UBI + device information and per UBI volume information (each UBI + device may have many UBI volumes) + +What: /sys/class/ubi/ubiX/avail_eraseblocks +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Amount of available logical eraseblock. For example, one may + create a new UBI volume which has this amount of logical + eraseblocks. + +What: /sys/class/ubi/ubiX/bad_peb_count +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Count of bad physical eraseblocks on the underlying MTD device. + +What: /sys/class/ubi/ubiX/bgt_enabled +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Contains ASCII "0\n" if the UBI background thread is disabled, + and ASCII "1\n" if it is enabled. + +What: /sys/class/ubi/ubiX/dev +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Major and minor numbers of the character device corresponding + to this UBI device (in : format). + +What: /sys/class/ubi/ubiX/eraseblock_size +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Maximum logical eraseblock size this UBI device may provide. UBI + volumes may have smaller logical eraseblock size because of their + alignment. + +What: /sys/class/ubi/ubiX/max_ec +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Maximum physical eraseblock erase counter value. + +What: /sys/class/ubi/ubiX/max_vol_count +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Maximum number of volumes which this UBI device may have. + +What: /sys/class/ubi/ubiX/min_io_size +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Minimum input/output unit size. All the I/O may only be done + in fractions of the contained number. + +What: /sys/class/ubi/ubiX/mtd_num +Date: January 2008 +KernelVersion: 2.6.25 +Contact: Artem Bityutskiy +Description: + Number of the underlying MTD device. + +What: /sys/class/ubi/ubiX/reserved_for_bad +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Number of physical eraseblocks reserved for bad block handling. + +What: /sys/class/ubi/ubiX/total_eraseblocks +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Total number of good (not marked as bad) physical eraseblocks on + the underlying MTD device. + +What: /sys/class/ubi/ubiX/volumes_count +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Count of volumes on this UBI device. + +What: /sys/class/ubi/ubiX/ubiX_Y/ +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + The /sys/class/ubi/ubiX/ubiX_0/, /sys/class/ubi/ubiX/ubiX_1/, + etc directories describe UBI volumes on UBI device X (volumes + 0, 1, etc). + +What: /sys/class/ubi/ubiX/ubiX_Y/alignment +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Volume alignment - the value the logical eraseblock size of + this volume has to be aligned on. For example, 2048 means that + logical eraseblock size is multiple of 2048. In other words, + volume logical eraseblock size is UBI device logical eraseblock + size aligned to the alignment value. + +What: /sys/class/ubi/ubiX/ubiX_Y/corrupted +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Contains ASCII "0\n" if the UBI volume is OK, and ASCII "1\n" + if it is corrupted (e.g., due to an interrupted volume update). + +What: /sys/class/ubi/ubiX/ubiX_Y/data_bytes +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + The amount of data this volume contains. This value makes sense + only for static volumes, and for dynamic volume it equivalent + to the total volume size in bytes. + +What: /sys/class/ubi/ubiX/ubiX_Y/dev +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Major and minor numbers of the character device corresponding + to this UBI volume (in : format). + +What: /sys/class/ubi/ubiX/ubiX_Y/name +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Volume name. + +What: /sys/class/ubi/ubiX/ubiX_Y/reserved_ebs +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Count of physical eraseblock reserved for this volume. + Equivalent to the volume size in logical eraseblocks. + +What: /sys/class/ubi/ubiX/ubiX_Y/type +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Volume type. Contains ASCII "dynamic\n" for dynamic volumes and + "static\n" for static volumes. + +What: /sys/class/ubi/ubiX/ubiX_Y/upd_marker +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Contains ASCII "0\n" if the update marker is not set for this + volume, and "1\n" if it is set. The update marker is set when + volume update starts, and cleaned when it ends. So the presence + of the update marker indicates that the volume is being updated + at the moment of the update was interrupted. The later may be + checked using the "corrupted" sysfs file. + +What: /sys/class/ubi/ubiX/ubiX_Y/usable_eb_size +Date: July 2006 +KernelVersion: 2.6.22 +Contact: Artem Bityutskiy +Description: + Logical eraseblock size of this volume. Equivalent to logical + eraseblock size of the device aligned on the volume alignment + value. -- cgit v1.2.3 From 3833eecc183ce052e9ac96b39b45121a2d11ac16 Mon Sep 17 00:00:00 2001 From: Thomas Gleixner Date: Wed, 5 Mar 2008 18:28:15 +0100 Subject: Documentation: move timer related documentation to a single place We have two directories with timer related information in Documentation/: hrtimers/ and hrtimer/. timer_stats are not restricted to hrtimers. Move all those files into Documentation/timers where we can pile up other timer related docs as well. Pointed-out-by: Randy Dunlap Signed-off-by: Thomas Gleixner --- Documentation/00-INDEX | 6 +- Documentation/hrtimer/timer_stats.txt | 73 ---------- Documentation/hrtimers/highres.txt | 249 ---------------------------------- Documentation/hrtimers/hrtimers.txt | 178 ------------------------ Documentation/timers/highres.txt | 249 ++++++++++++++++++++++++++++++++++ Documentation/timers/hrtimers.txt | 178 ++++++++++++++++++++++++ Documentation/timers/timer_stats.txt | 73 ++++++++++ 7 files changed, 502 insertions(+), 504 deletions(-) delete mode 100644 Documentation/hrtimer/timer_stats.txt delete mode 100644 Documentation/hrtimers/highres.txt delete mode 100644 Documentation/hrtimers/hrtimers.txt create mode 100644 Documentation/timers/highres.txt create mode 100644 Documentation/timers/hrtimers.txt create mode 100644 Documentation/timers/timer_stats.txt (limited to 'Documentation') diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index e8fb24671967..f7923a42e769 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -167,10 +167,8 @@ highuid.txt - notes on the change from 16 bit to 32 bit user/group IDs. hpet.txt - High Precision Event Timer Driver for Linux. -hrtimer/ - - info on the timer_stats debugging facility for timer (ab)use. -hrtimers/ - - info on the hrtimers subsystem for high-resolution kernel timers. +timers/ + - info on the timer related topics hw_random.txt - info on Linux support for random number generator in i8xx chipsets. hwmon/ diff --git a/Documentation/hrtimer/timer_stats.txt b/Documentation/hrtimer/timer_stats.txt deleted file mode 100644 index 20d368c59814..000000000000 --- a/Documentation/hrtimer/timer_stats.txt +++ /dev/null @@ -1,73 +0,0 @@ -timer_stats - timer usage statistics ------------------------------------- - -timer_stats is a debugging facility to make the timer (ab)usage in a Linux -system visible to kernel and userspace developers. If enabled in the config -but not used it has almost zero runtime overhead, and a relatively small -data structure overhead. Even if collection is enabled runtime all the -locking is per-CPU and lookup is hashed. - -timer_stats should be used by kernel and userspace developers to verify that -their code does not make unduly use of timers. This helps to avoid unnecessary -wakeups, which should be avoided to optimize power consumption. - -It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration -section. - -timer_stats collects information about the timer events which are fired in a -Linux system over a sample period: - -- the pid of the task(process) which initialized the timer -- the name of the process which initialized the timer -- the function where the timer was intialized -- the callback function which is associated to the timer -- the number of events (callbacks) - -timer_stats adds an entry to /proc: /proc/timer_stats - -This entry is used to control the statistics functionality and to read out the -sampled information. - -The timer_stats functionality is inactive on bootup. - -To activate a sample period issue: -# echo 1 >/proc/timer_stats - -To stop a sample period issue: -# echo 0 >/proc/timer_stats - -The statistics can be retrieved by: -# cat /proc/timer_stats - -The readout of /proc/timer_stats automatically disables sampling. The sampled -information is kept until a new sample period is started. This allows multiple -readouts. - -Sample output of /proc/timer_stats: - -Timerstats sample period: 3.888770 s - 12, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) - 15, 1 swapper hcd_submit_urb (rh_timer_func) - 4, 959 kedac schedule_timeout (process_timeout) - 1, 0 swapper page_writeback_init (wb_timer_fn) - 28, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) - 22, 2948 IRQ 4 tty_flip_buffer_push (delayed_work_timer_fn) - 3, 3100 bash schedule_timeout (process_timeout) - 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) - 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) - 1, 1 swapper neigh_table_init_no_netlink (neigh_periodic_timer) - 1, 2292 ip __netdev_watchdog_up (dev_watchdog) - 1, 23 events/1 do_cache_clean (delayed_work_timer_fn) -90 total events, 30.0 events/sec - -The first column is the number of events, the second column the pid, the third -column is the name of the process. The forth column shows the function which -initialized the timer and in parantheses the callback function which was -executed on expiry. - - Thomas, Ingo - -Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable -timer will appear as follows - 10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) - diff --git a/Documentation/hrtimers/highres.txt b/Documentation/hrtimers/highres.txt deleted file mode 100644 index a73ecf5b4bdb..000000000000 --- a/Documentation/hrtimers/highres.txt +++ /dev/null @@ -1,249 +0,0 @@ -High resolution timers and dynamic ticks design notes ------------------------------------------------------ - -Further information can be found in the paper of the OLS 2006 talk "hrtimers -and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can -be found on the OLS website: -http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf - -The slides to this talk are available from: -http://tglx.de/projects/hrtimers/ols2006-hrtimers.pdf - -The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the -changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the -design of the Linux time(r) system before hrtimers and other building blocks -got merged into mainline. - -Note: the paper and the slides are talking about "clock event source", while we -switched to the name "clock event devices" in meantime. - -The design contains the following basic building blocks: - -- hrtimer base infrastructure -- timeofday and clock source management -- clock event management -- high resolution timer functionality -- dynamic ticks - - -hrtimer base infrastructure ---------------------------- - -The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of -the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See -also figure #2 (OLS slides p. 15) - -The main differences to the timer wheel, which holds the armed timer_list type -timers are: - - time ordered enqueueing into a rb-tree - - independent of ticks (the processing is based on nanoseconds) - - -timeofday and clock source management -------------------------------------- - -John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of -code out of the architecture-specific areas into a generic management -framework, as illustrated in figure #3 (OLS slides p. 18). The architecture -specific portion is reduced to the low level hardware details of the clock -sources, which are registered in the framework and selected on a quality based -decision. The low level code provides hardware setup and readout routines and -initializes data structures, which are used by the generic time keeping code to -convert the clock ticks to nanosecond based time values. All other time keeping -related functionality is moved into the generic code. The GTOD base patch got -merged into the 2.6.18 kernel. - -Further information about the Generic Time Of Day framework is available in the -OLS 2005 Proceedings Volume 1: -http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf - -The paper "We Are Not Getting Any Younger: A New Approach to Time and -Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan. - -Figure #3 (OLS slides p.18) illustrates the transformation. - - -clock event management ----------------------- - -While clock sources provide read access to the monotonically increasing time -value, clock event devices are used to schedule the next event -interrupt(s). The next event is currently defined to be periodic, with its -period defined at compile time. The setup and selection of the event device -for various event driven functionalities is hardwired into the architecture -dependent code. This results in duplicated code across all architectures and -makes it extremely difficult to change the configuration of the system to use -event interrupt devices other than those already built into the -architecture. Another implication of the current design is that it is necessary -to touch all the architecture-specific implementations in order to provide new -functionality like high resolution timers or dynamic ticks. - -The clock events subsystem tries to address this problem by providing a generic -solution to manage clock event devices and their usage for the various clock -event driven kernel functionalities. The goal of the clock event subsystem is -to minimize the clock event related architecture dependent code to the pure -hardware related handling and to allow easy addition and utilization of new -clock event devices. It also minimizes the duplicated code across the -architectures as it provides generic functionality down to the interrupt -service handler, which is almost inherently hardware dependent. - -Clock event devices are registered either by the architecture dependent boot -code or at module insertion time. Each clock event device fills a data -structure with clock-specific property parameters and callback functions. The -clock event management decides, by using the specified property parameters, the -set of system functions a clock event device will be used to support. This -includes the distinction of per-CPU and per-system global event devices. - -System-level global event devices are used for the Linux periodic tick. Per-CPU -event devices are used to provide local CPU functionality such as process -accounting, profiling, and high resolution timers. - -The management layer assigns one or more of the following functions to a clock -event device: - - system global periodic tick (jiffies update) - - cpu local update_process_times - - cpu local profiling - - cpu local next event interrupt (non periodic mode) - -The clock event device delegates the selection of those timer interrupt related -functions completely to the management layer. The clock management layer stores -a function pointer in the device description structure, which has to be called -from the hardware level handler. This removes a lot of duplicated code from the -architecture specific timer interrupt handlers and hands the control over the -clock event devices and the assignment of timer interrupt related functionality -to the core code. - -The clock event layer API is rather small. Aside from the clock event device -registration interface it provides functions to schedule the next event -interrupt, clock event device notification service and support for suspend and -resume. - -The framework adds about 700 lines of code which results in a 2KB increase of -the kernel binary size. The conversion of i386 removes about 100 lines of -code. The binary size decrease is in the range of 400 byte. We believe that the -increase of flexibility and the avoidance of duplicated code across -architectures justifies the slight increase of the binary size. - -The conversion of an architecture has no functional impact, but allows to -utilize the high resolution and dynamic tick functionalites without any change -to the clock event device and timer interrupt code. After the conversion the -enabling of high resolution timers and dynamic ticks is simply provided by -adding the kernel/time/Kconfig file to the architecture specific Kconfig and -adding the dynamic tick specific calls to the idle routine (a total of 3 lines -added to the idle function and the Kconfig file) - -Figure #4 (OLS slides p.20) illustrates the transformation. - - -high resolution timer functionality ------------------------------------ - -During system boot it is not possible to use the high resolution timer -functionality, while making it possible would be difficult and would serve no -useful function. The initialization of the clock event device framework, the -clock source framework (GTOD) and hrtimers itself has to be done and -appropriate clock sources and clock event devices have to be registered before -the high resolution functionality can work. Up to the point where hrtimers are -initialized, the system works in the usual low resolution periodic mode. The -clock source and the clock event device layers provide notification functions -which inform hrtimers about availability of new hardware. hrtimers validates -the usability of the registered clock sources and clock event devices before -switching to high resolution mode. This ensures also that a kernel which is -configured for high resolution timers can run on a system which lacks the -necessary hardware support. - -The high resolution timer code does not support SMP machines which have only -global clock event devices. The support of such hardware would involve IPI -calls when an interrupt happens. The overhead would be much larger than the -benefit. This is the reason why we currently disable high resolution and -dynamic ticks on i386 SMP systems which stop the local APIC in C3 power -state. A workaround is available as an idea, but the problem has not been -tackled yet. - -The time ordered insertion of timers provides all the infrastructure to decide -whether the event device has to be reprogrammed when a timer is added. The -decision is made per timer base and synchronized across per-cpu timer bases in -a support function. The design allows the system to utilize separate per-CPU -clock event devices for the per-CPU timer bases, but currently only one -reprogrammable clock event device per-CPU is utilized. - -When the timer interrupt happens, the next event interrupt handler is called -from the clock event distribution code and moves expired timers from the -red-black tree to a separate double linked list and invokes the softirq -handler. An additional mode field in the hrtimer structure allows the system to -execute callback functions directly from the next event interrupt handler. This -is restricted to code which can safely be executed in the hard interrupt -context. This applies, for example, to the common case of a wakeup function as -used by nanosleep. The advantage of executing the handler in the interrupt -context is the avoidance of up to two context switches - from the interrupted -context to the softirq and to the task which is woken up by the expired -timer. - -Once a system has switched to high resolution mode, the periodic tick is -switched off. This disables the per system global periodic clock event device - -e.g. the PIT on i386 SMP systems. - -The periodic tick functionality is provided by an per-cpu hrtimer. The callback -function is executed in the next event interrupt context and updates jiffies -and calls update_process_times and profiling. The implementation of the hrtimer -based periodic tick is designed to be extended with dynamic tick functionality. -This allows to use a single clock event device to schedule high resolution -timer and periodic events (jiffies tick, profiling, process accounting) on UP -systems. This has been proved to work with the PIT on i386 and the Incrementer -on PPC. - -The softirq for running the hrtimer queues and executing the callbacks has been -separated from the tick bound timer softirq to allow accurate delivery of high -resolution timer signals which are used by itimer and POSIX interval -timers. The execution of this softirq can still be delayed by other softirqs, -but the overall latencies have been significantly improved by this separation. - -Figure #5 (OLS slides p.22) illustrates the transformation. - - -dynamic ticks -------------- - -Dynamic ticks are the logical consequence of the hrtimer based periodic tick -replacement (sched_tick). The functionality of the sched_tick hrtimer is -extended by three functions: - -- hrtimer_stop_sched_tick -- hrtimer_restart_sched_tick -- hrtimer_update_jiffies - -hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code -evaluates the next scheduled timer event (from both hrtimers and the timer -wheel) and in case that the next event is further away than the next tick it -reprograms the sched_tick to this future event, to allow longer idle sleeps -without worthless interruption by the periodic tick. The function is also -called when an interrupt happens during the idle period, which does not cause a -reschedule. The call is necessary as the interrupt handler might have armed a -new timer whose expiry time is before the time which was identified as the -nearest event in the previous call to hrtimer_stop_sched_tick. - -hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before -it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick, -which is kept active until the next call to hrtimer_stop_sched_tick(). - -hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens -in the idle period to make sure that jiffies are up to date and the interrupt -handler has not to deal with an eventually stale jiffy value. - -The dynamic tick feature provides statistical values which are exported to -userspace via /proc/stats and can be made available for enhanced power -management control. - -The implementation leaves room for further development like full tickless -systems, where the time slice is controlled by the scheduler, variable -frequency profiling, and a complete removal of jiffies in the future. - - -Aside the current initial submission of i386 support, the patchset has been -extended to x86_64 and ARM already. Initial (work in progress) support is also -available for MIPS and PowerPC. - - Thomas, Ingo - - - diff --git a/Documentation/hrtimers/hrtimers.txt b/Documentation/hrtimers/hrtimers.txt deleted file mode 100644 index ce31f65e12e7..000000000000 --- a/Documentation/hrtimers/hrtimers.txt +++ /dev/null @@ -1,178 +0,0 @@ - -hrtimers - subsystem for high-resolution kernel timers ----------------------------------------------------- - -This patch introduces a new subsystem for high-resolution kernel timers. - -One might ask the question: we already have a timer subsystem -(kernel/timers.c), why do we need two timer subsystems? After a lot of -back and forth trying to integrate high-resolution and high-precision -features into the existing timer framework, and after testing various -such high-resolution timer implementations in practice, we came to the -conclusion that the timer wheel code is fundamentally not suitable for -such an approach. We initially didn't believe this ('there must be a way -to solve this'), and spent a considerable effort trying to integrate -things into the timer wheel, but we failed. In hindsight, there are -several reasons why such integration is hard/impossible: - -- the forced handling of low-resolution and high-resolution timers in - the same way leads to a lot of compromises, macro magic and #ifdef - mess. The timers.c code is very "tightly coded" around jiffies and - 32-bitness assumptions, and has been honed and micro-optimized for a - relatively narrow use case (jiffies in a relatively narrow HZ range) - for many years - and thus even small extensions to it easily break - the wheel concept, leading to even worse compromises. The timer wheel - code is very good and tight code, there's zero problems with it in its - current usage - but it is simply not suitable to be extended for - high-res timers. - -- the unpredictable [O(N)] overhead of cascading leads to delays which - necessitate a more complex handling of high resolution timers, which - in turn decreases robustness. Such a design still led to rather large - timing inaccuracies. Cascading is a fundamental property of the timer - wheel concept, it cannot be 'designed out' without unevitably - degrading other portions of the timers.c code in an unacceptable way. - -- the implementation of the current posix-timer subsystem on top of - the timer wheel has already introduced a quite complex handling of - the required readjusting of absolute CLOCK_REALTIME timers at - settimeofday or NTP time - further underlying our experience by - example: that the timer wheel data structure is too rigid for high-res - timers. - -- the timer wheel code is most optimal for use cases which can be - identified as "timeouts". Such timeouts are usually set up to cover - error conditions in various I/O paths, such as networking and block - I/O. The vast majority of those timers never expire and are rarely - recascaded because the expected correct event arrives in time so they - can be removed from the timer wheel before any further processing of - them becomes necessary. Thus the users of these timeouts can accept - the granularity and precision tradeoffs of the timer wheel, and - largely expect the timer subsystem to have near-zero overhead. - Accurate timing for them is not a core purpose - in fact most of the - timeout values used are ad-hoc. For them it is at most a necessary - evil to guarantee the processing of actual timeout completions - (because most of the timeouts are deleted before completion), which - should thus be as cheap and unintrusive as possible. - -The primary users of precision timers are user-space applications that -utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel -users like drivers and subsystems which require precise timed events -(e.g. multimedia) can benefit from the availability of a separate -high-resolution timer subsystem as well. - -While this subsystem does not offer high-resolution clock sources just -yet, the hrtimer subsystem can be easily extended with high-resolution -clock capabilities, and patches for that exist and are maturing quickly. -The increasing demand for realtime and multimedia applications along -with other potential users for precise timers gives another reason to -separate the "timeout" and "precise timer" subsystems. - -Another potential benefit is that such a separation allows even more -special-purpose optimization of the existing timer wheel for the low -resolution and low precision use cases - once the precision-sensitive -APIs are separated from the timer wheel and are migrated over to -hrtimers. E.g. we could decrease the frequency of the timeout subsystem -from 250 Hz to 100 HZ (or even smaller). - -hrtimer subsystem implementation details ----------------------------------------- - -the basic design considerations were: - -- simplicity - -- data structure not bound to jiffies or any other granularity. All the - kernel logic works at 64-bit nanoseconds resolution - no compromises. - -- simplification of existing, timing related kernel code - -another basic requirement was the immediate enqueueing and ordering of -timers at activation time. After looking at several possible solutions -such as radix trees and hashes, we chose the red black tree as the basic -data structure. Rbtrees are available as a library in the kernel and are -used in various performance-critical areas of e.g. memory management and -file systems. The rbtree is solely used for time sorted ordering, while -a separate list is used to give the expiry code fast access to the -queued timers, without having to walk the rbtree. - -(This separate list is also useful for later when we'll introduce -high-resolution clocks, where we need separate pending and expired -queues while keeping the time-order intact.) - -Time-ordered enqueueing is not purely for the purposes of -high-resolution clocks though, it also simplifies the handling of -absolute timers based on a low-resolution CLOCK_REALTIME. The existing -implementation needed to keep an extra list of all armed absolute -CLOCK_REALTIME timers along with complex locking. In case of -settimeofday and NTP, all the timers (!) had to be dequeued, the -time-changing code had to fix them up one by one, and all of them had to -be enqueued again. The time-ordered enqueueing and the storage of the -expiry time in absolute time units removes all this complex and poorly -scaling code from the posix-timer implementation - the clock can simply -be set without having to touch the rbtree. This also makes the handling -of posix-timers simpler in general. - -The locking and per-CPU behavior of hrtimers was mostly taken from the -existing timer wheel code, as it is mature and well suited. Sharing code -was not really a win, due to the different data structures. Also, the -hrtimer functions now have clearer behavior and clearer names - such as -hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly -equivalent to del_timer() and del_timer_sync()] - so there's no direct -1:1 mapping between them on the algorithmical level, and thus no real -potential for code sharing either. - -Basic data types: every time value, absolute or relative, is in a -special nanosecond-resolution type: ktime_t. The kernel-internal -representation of ktime_t values and operations is implemented via -macros and inline functions, and can be switched between a "hybrid -union" type and a plain "scalar" 64bit nanoseconds representation (at -compile time). The hybrid union type optimizes time conversions on 32bit -CPUs. This build-time-selectable ktime_t storage format was implemented -to avoid the performance impact of 64-bit multiplications and divisions -on 32bit CPUs. Such operations are frequently necessary to convert -between the storage formats provided by kernel and userspace interfaces -and the internal time format. (See include/linux/ktime.h for further -details.) - -hrtimers - rounding of timer values ------------------------------------ - -the hrtimer code will round timer events to lower-resolution clocks -because it has to. Otherwise it will do no artificial rounding at all. - -one question is, what resolution value should be returned to the user by -the clock_getres() interface. This will return whatever real resolution -a given clock has - be it low-res, high-res, or artificially-low-res. - -hrtimers - testing and verification ----------------------------------- - -We used the high-resolution clock subsystem ontop of hrtimers to verify -the hrtimer implementation details in praxis, and we also ran the posix -timer tests in order to ensure specification compliance. We also ran -tests on low-resolution clocks. - -The hrtimer patch converts the following kernel functionality to use -hrtimers: - - - nanosleep - - itimers - - posix-timers - -The conversion of nanosleep and posix-timers enabled the unification of -nanosleep and clock_nanosleep. - -The code was successfully compiled for the following platforms: - - i386, x86_64, ARM, PPC, PPC64, IA64 - -The code was run-tested on the following platforms: - - i386(UP/SMP), x86_64(UP/SMP), ARM, PPC - -hrtimers were also integrated into the -rt tree, along with a -hrtimers-based high-resolution clock implementation, so the hrtimers -code got a healthy amount of testing and use in practice. - - Thomas Gleixner, Ingo Molnar diff --git a/Documentation/timers/highres.txt b/Documentation/timers/highres.txt new file mode 100644 index 000000000000..a73ecf5b4bdb --- /dev/null +++ b/Documentation/timers/highres.txt @@ -0,0 +1,249 @@ +High resolution timers and dynamic ticks design notes +----------------------------------------------------- + +Further information can be found in the paper of the OLS 2006 talk "hrtimers +and beyond". The paper is part of the OLS 2006 Proceedings Volume 1, which can +be found on the OLS website: +http://www.linuxsymposium.org/2006/linuxsymposium_procv1.pdf + +The slides to this talk are available from: +http://tglx.de/projects/hrtimers/ols2006-hrtimers.pdf + +The slides contain five figures (pages 2, 15, 18, 20, 22), which illustrate the +changes in the time(r) related Linux subsystems. Figure #1 (p. 2) shows the +design of the Linux time(r) system before hrtimers and other building blocks +got merged into mainline. + +Note: the paper and the slides are talking about "clock event source", while we +switched to the name "clock event devices" in meantime. + +The design contains the following basic building blocks: + +- hrtimer base infrastructure +- timeofday and clock source management +- clock event management +- high resolution timer functionality +- dynamic ticks + + +hrtimer base infrastructure +--------------------------- + +The hrtimer base infrastructure was merged into the 2.6.16 kernel. Details of +the base implementation are covered in Documentation/hrtimers/hrtimer.txt. See +also figure #2 (OLS slides p. 15) + +The main differences to the timer wheel, which holds the armed timer_list type +timers are: + - time ordered enqueueing into a rb-tree + - independent of ticks (the processing is based on nanoseconds) + + +timeofday and clock source management +------------------------------------- + +John Stultz's Generic Time Of Day (GTOD) framework moves a large portion of +code out of the architecture-specific areas into a generic management +framework, as illustrated in figure #3 (OLS slides p. 18). The architecture +specific portion is reduced to the low level hardware details of the clock +sources, which are registered in the framework and selected on a quality based +decision. The low level code provides hardware setup and readout routines and +initializes data structures, which are used by the generic time keeping code to +convert the clock ticks to nanosecond based time values. All other time keeping +related functionality is moved into the generic code. The GTOD base patch got +merged into the 2.6.18 kernel. + +Further information about the Generic Time Of Day framework is available in the +OLS 2005 Proceedings Volume 1: +http://www.linuxsymposium.org/2005/linuxsymposium_procv1.pdf + +The paper "We Are Not Getting Any Younger: A New Approach to Time and +Timers" was written by J. Stultz, D.V. Hart, & N. Aravamudan. + +Figure #3 (OLS slides p.18) illustrates the transformation. + + +clock event management +---------------------- + +While clock sources provide read access to the monotonically increasing time +value, clock event devices are used to schedule the next event +interrupt(s). The next event is currently defined to be periodic, with its +period defined at compile time. The setup and selection of the event device +for various event driven functionalities is hardwired into the architecture +dependent code. This results in duplicated code across all architectures and +makes it extremely difficult to change the configuration of the system to use +event interrupt devices other than those already built into the +architecture. Another implication of the current design is that it is necessary +to touch all the architecture-specific implementations in order to provide new +functionality like high resolution timers or dynamic ticks. + +The clock events subsystem tries to address this problem by providing a generic +solution to manage clock event devices and their usage for the various clock +event driven kernel functionalities. The goal of the clock event subsystem is +to minimize the clock event related architecture dependent code to the pure +hardware related handling and to allow easy addition and utilization of new +clock event devices. It also minimizes the duplicated code across the +architectures as it provides generic functionality down to the interrupt +service handler, which is almost inherently hardware dependent. + +Clock event devices are registered either by the architecture dependent boot +code or at module insertion time. Each clock event device fills a data +structure with clock-specific property parameters and callback functions. The +clock event management decides, by using the specified property parameters, the +set of system functions a clock event device will be used to support. This +includes the distinction of per-CPU and per-system global event devices. + +System-level global event devices are used for the Linux periodic tick. Per-CPU +event devices are used to provide local CPU functionality such as process +accounting, profiling, and high resolution timers. + +The management layer assigns one or more of the following functions to a clock +event device: + - system global periodic tick (jiffies update) + - cpu local update_process_times + - cpu local profiling + - cpu local next event interrupt (non periodic mode) + +The clock event device delegates the selection of those timer interrupt related +functions completely to the management layer. The clock management layer stores +a function pointer in the device description structure, which has to be called +from the hardware level handler. This removes a lot of duplicated code from the +architecture specific timer interrupt handlers and hands the control over the +clock event devices and the assignment of timer interrupt related functionality +to the core code. + +The clock event layer API is rather small. Aside from the clock event device +registration interface it provides functions to schedule the next event +interrupt, clock event device notification service and support for suspend and +resume. + +The framework adds about 700 lines of code which results in a 2KB increase of +the kernel binary size. The conversion of i386 removes about 100 lines of +code. The binary size decrease is in the range of 400 byte. We believe that the +increase of flexibility and the avoidance of duplicated code across +architectures justifies the slight increase of the binary size. + +The conversion of an architecture has no functional impact, but allows to +utilize the high resolution and dynamic tick functionalites without any change +to the clock event device and timer interrupt code. After the conversion the +enabling of high resolution timers and dynamic ticks is simply provided by +adding the kernel/time/Kconfig file to the architecture specific Kconfig and +adding the dynamic tick specific calls to the idle routine (a total of 3 lines +added to the idle function and the Kconfig file) + +Figure #4 (OLS slides p.20) illustrates the transformation. + + +high resolution timer functionality +----------------------------------- + +During system boot it is not possible to use the high resolution timer +functionality, while making it possible would be difficult and would serve no +useful function. The initialization of the clock event device framework, the +clock source framework (GTOD) and hrtimers itself has to be done and +appropriate clock sources and clock event devices have to be registered before +the high resolution functionality can work. Up to the point where hrtimers are +initialized, the system works in the usual low resolution periodic mode. The +clock source and the clock event device layers provide notification functions +which inform hrtimers about availability of new hardware. hrtimers validates +the usability of the registered clock sources and clock event devices before +switching to high resolution mode. This ensures also that a kernel which is +configured for high resolution timers can run on a system which lacks the +necessary hardware support. + +The high resolution timer code does not support SMP machines which have only +global clock event devices. The support of such hardware would involve IPI +calls when an interrupt happens. The overhead would be much larger than the +benefit. This is the reason why we currently disable high resolution and +dynamic ticks on i386 SMP systems which stop the local APIC in C3 power +state. A workaround is available as an idea, but the problem has not been +tackled yet. + +The time ordered insertion of timers provides all the infrastructure to decide +whether the event device has to be reprogrammed when a timer is added. The +decision is made per timer base and synchronized across per-cpu timer bases in +a support function. The design allows the system to utilize separate per-CPU +clock event devices for the per-CPU timer bases, but currently only one +reprogrammable clock event device per-CPU is utilized. + +When the timer interrupt happens, the next event interrupt handler is called +from the clock event distribution code and moves expired timers from the +red-black tree to a separate double linked list and invokes the softirq +handler. An additional mode field in the hrtimer structure allows the system to +execute callback functions directly from the next event interrupt handler. This +is restricted to code which can safely be executed in the hard interrupt +context. This applies, for example, to the common case of a wakeup function as +used by nanosleep. The advantage of executing the handler in the interrupt +context is the avoidance of up to two context switches - from the interrupted +context to the softirq and to the task which is woken up by the expired +timer. + +Once a system has switched to high resolution mode, the periodic tick is +switched off. This disables the per system global periodic clock event device - +e.g. the PIT on i386 SMP systems. + +The periodic tick functionality is provided by an per-cpu hrtimer. The callback +function is executed in the next event interrupt context and updates jiffies +and calls update_process_times and profiling. The implementation of the hrtimer +based periodic tick is designed to be extended with dynamic tick functionality. +This allows to use a single clock event device to schedule high resolution +timer and periodic events (jiffies tick, profiling, process accounting) on UP +systems. This has been proved to work with the PIT on i386 and the Incrementer +on PPC. + +The softirq for running the hrtimer queues and executing the callbacks has been +separated from the tick bound timer softirq to allow accurate delivery of high +resolution timer signals which are used by itimer and POSIX interval +timers. The execution of this softirq can still be delayed by other softirqs, +but the overall latencies have been significantly improved by this separation. + +Figure #5 (OLS slides p.22) illustrates the transformation. + + +dynamic ticks +------------- + +Dynamic ticks are the logical consequence of the hrtimer based periodic tick +replacement (sched_tick). The functionality of the sched_tick hrtimer is +extended by three functions: + +- hrtimer_stop_sched_tick +- hrtimer_restart_sched_tick +- hrtimer_update_jiffies + +hrtimer_stop_sched_tick() is called when a CPU goes into idle state. The code +evaluates the next scheduled timer event (from both hrtimers and the timer +wheel) and in case that the next event is further away than the next tick it +reprograms the sched_tick to this future event, to allow longer idle sleeps +without worthless interruption by the periodic tick. The function is also +called when an interrupt happens during the idle period, which does not cause a +reschedule. The call is necessary as the interrupt handler might have armed a +new timer whose expiry time is before the time which was identified as the +nearest event in the previous call to hrtimer_stop_sched_tick. + +hrtimer_restart_sched_tick() is called when the CPU leaves the idle state before +it calls schedule(). hrtimer_restart_sched_tick() resumes the periodic tick, +which is kept active until the next call to hrtimer_stop_sched_tick(). + +hrtimer_update_jiffies() is called from irq_enter() when an interrupt happens +in the idle period to make sure that jiffies are up to date and the interrupt +handler has not to deal with an eventually stale jiffy value. + +The dynamic tick feature provides statistical values which are exported to +userspace via /proc/stats and can be made available for enhanced power +management control. + +The implementation leaves room for further development like full tickless +systems, where the time slice is controlled by the scheduler, variable +frequency profiling, and a complete removal of jiffies in the future. + + +Aside the current initial submission of i386 support, the patchset has been +extended to x86_64 and ARM already. Initial (work in progress) support is also +available for MIPS and PowerPC. + + Thomas, Ingo + + + diff --git a/Documentation/timers/hrtimers.txt b/Documentation/timers/hrtimers.txt new file mode 100644 index 000000000000..ce31f65e12e7 --- /dev/null +++ b/Documentation/timers/hrtimers.txt @@ -0,0 +1,178 @@ + +hrtimers - subsystem for high-resolution kernel timers +---------------------------------------------------- + +This patch introduces a new subsystem for high-resolution kernel timers. + +One might ask the question: we already have a timer subsystem +(kernel/timers.c), why do we need two timer subsystems? After a lot of +back and forth trying to integrate high-resolution and high-precision +features into the existing timer framework, and after testing various +such high-resolution timer implementations in practice, we came to the +conclusion that the timer wheel code is fundamentally not suitable for +such an approach. We initially didn't believe this ('there must be a way +to solve this'), and spent a considerable effort trying to integrate +things into the timer wheel, but we failed. In hindsight, there are +several reasons why such integration is hard/impossible: + +- the forced handling of low-resolution and high-resolution timers in + the same way leads to a lot of compromises, macro magic and #ifdef + mess. The timers.c code is very "tightly coded" around jiffies and + 32-bitness assumptions, and has been honed and micro-optimized for a + relatively narrow use case (jiffies in a relatively narrow HZ range) + for many years - and thus even small extensions to it easily break + the wheel concept, leading to even worse compromises. The timer wheel + code is very good and tight code, there's zero problems with it in its + current usage - but it is simply not suitable to be extended for + high-res timers. + +- the unpredictable [O(N)] overhead of cascading leads to delays which + necessitate a more complex handling of high resolution timers, which + in turn decreases robustness. Such a design still led to rather large + timing inaccuracies. Cascading is a fundamental property of the timer + wheel concept, it cannot be 'designed out' without unevitably + degrading other portions of the timers.c code in an unacceptable way. + +- the implementation of the current posix-timer subsystem on top of + the timer wheel has already introduced a quite complex handling of + the required readjusting of absolute CLOCK_REALTIME timers at + settimeofday or NTP time - further underlying our experience by + example: that the timer wheel data structure is too rigid for high-res + timers. + +- the timer wheel code is most optimal for use cases which can be + identified as "timeouts". Such timeouts are usually set up to cover + error conditions in various I/O paths, such as networking and block + I/O. The vast majority of those timers never expire and are rarely + recascaded because the expected correct event arrives in time so they + can be removed from the timer wheel before any further processing of + them becomes necessary. Thus the users of these timeouts can accept + the granularity and precision tradeoffs of the timer wheel, and + largely expect the timer subsystem to have near-zero overhead. + Accurate timing for them is not a core purpose - in fact most of the + timeout values used are ad-hoc. For them it is at most a necessary + evil to guarantee the processing of actual timeout completions + (because most of the timeouts are deleted before completion), which + should thus be as cheap and unintrusive as possible. + +The primary users of precision timers are user-space applications that +utilize nanosleep, posix-timers and itimer interfaces. Also, in-kernel +users like drivers and subsystems which require precise timed events +(e.g. multimedia) can benefit from the availability of a separate +high-resolution timer subsystem as well. + +While this subsystem does not offer high-resolution clock sources just +yet, the hrtimer subsystem can be easily extended with high-resolution +clock capabilities, and patches for that exist and are maturing quickly. +The increasing demand for realtime and multimedia applications along +with other potential users for precise timers gives another reason to +separate the "timeout" and "precise timer" subsystems. + +Another potential benefit is that such a separation allows even more +special-purpose optimization of the existing timer wheel for the low +resolution and low precision use cases - once the precision-sensitive +APIs are separated from the timer wheel and are migrated over to +hrtimers. E.g. we could decrease the frequency of the timeout subsystem +from 250 Hz to 100 HZ (or even smaller). + +hrtimer subsystem implementation details +---------------------------------------- + +the basic design considerations were: + +- simplicity + +- data structure not bound to jiffies or any other granularity. All the + kernel logic works at 64-bit nanoseconds resolution - no compromises. + +- simplification of existing, timing related kernel code + +another basic requirement was the immediate enqueueing and ordering of +timers at activation time. After looking at several possible solutions +such as radix trees and hashes, we chose the red black tree as the basic +data structure. Rbtrees are available as a library in the kernel and are +used in various performance-critical areas of e.g. memory management and +file systems. The rbtree is solely used for time sorted ordering, while +a separate list is used to give the expiry code fast access to the +queued timers, without having to walk the rbtree. + +(This separate list is also useful for later when we'll introduce +high-resolution clocks, where we need separate pending and expired +queues while keeping the time-order intact.) + +Time-ordered enqueueing is not purely for the purposes of +high-resolution clocks though, it also simplifies the handling of +absolute timers based on a low-resolution CLOCK_REALTIME. The existing +implementation needed to keep an extra list of all armed absolute +CLOCK_REALTIME timers along with complex locking. In case of +settimeofday and NTP, all the timers (!) had to be dequeued, the +time-changing code had to fix them up one by one, and all of them had to +be enqueued again. The time-ordered enqueueing and the storage of the +expiry time in absolute time units removes all this complex and poorly +scaling code from the posix-timer implementation - the clock can simply +be set without having to touch the rbtree. This also makes the handling +of posix-timers simpler in general. + +The locking and per-CPU behavior of hrtimers was mostly taken from the +existing timer wheel code, as it is mature and well suited. Sharing code +was not really a win, due to the different data structures. Also, the +hrtimer functions now have clearer behavior and clearer names - such as +hrtimer_try_to_cancel() and hrtimer_cancel() [which are roughly +equivalent to del_timer() and del_timer_sync()] - so there's no direct +1:1 mapping between them on the algorithmical level, and thus no real +potential for code sharing either. + +Basic data types: every time value, absolute or relative, is in a +special nanosecond-resolution type: ktime_t. The kernel-internal +representation of ktime_t values and operations is implemented via +macros and inline functions, and can be switched between a "hybrid +union" type and a plain "scalar" 64bit nanoseconds representation (at +compile time). The hybrid union type optimizes time conversions on 32bit +CPUs. This build-time-selectable ktime_t storage format was implemented +to avoid the performance impact of 64-bit multiplications and divisions +on 32bit CPUs. Such operations are frequently necessary to convert +between the storage formats provided by kernel and userspace interfaces +and the internal time format. (See include/linux/ktime.h for further +details.) + +hrtimers - rounding of timer values +----------------------------------- + +the hrtimer code will round timer events to lower-resolution clocks +because it has to. Otherwise it will do no artificial rounding at all. + +one question is, what resolution value should be returned to the user by +the clock_getres() interface. This will return whatever real resolution +a given clock has - be it low-res, high-res, or artificially-low-res. + +hrtimers - testing and verification +---------------------------------- + +We used the high-resolution clock subsystem ontop of hrtimers to verify +the hrtimer implementation details in praxis, and we also ran the posix +timer tests in order to ensure specification compliance. We also ran +tests on low-resolution clocks. + +The hrtimer patch converts the following kernel functionality to use +hrtimers: + + - nanosleep + - itimers + - posix-timers + +The conversion of nanosleep and posix-timers enabled the unification of +nanosleep and clock_nanosleep. + +The code was successfully compiled for the following platforms: + + i386, x86_64, ARM, PPC, PPC64, IA64 + +The code was run-tested on the following platforms: + + i386(UP/SMP), x86_64(UP/SMP), ARM, PPC + +hrtimers were also integrated into the -rt tree, along with a +hrtimers-based high-resolution clock implementation, so the hrtimers +code got a healthy amount of testing and use in practice. + + Thomas Gleixner, Ingo Molnar diff --git a/Documentation/timers/timer_stats.txt b/Documentation/timers/timer_stats.txt new file mode 100644 index 000000000000..20d368c59814 --- /dev/null +++ b/Documentation/timers/timer_stats.txt @@ -0,0 +1,73 @@ +timer_stats - timer usage statistics +------------------------------------ + +timer_stats is a debugging facility to make the timer (ab)usage in a Linux +system visible to kernel and userspace developers. If enabled in the config +but not used it has almost zero runtime overhead, and a relatively small +data structure overhead. Even if collection is enabled runtime all the +locking is per-CPU and lookup is hashed. + +timer_stats should be used by kernel and userspace developers to verify that +their code does not make unduly use of timers. This helps to avoid unnecessary +wakeups, which should be avoided to optimize power consumption. + +It can be enabled by CONFIG_TIMER_STATS in the "Kernel hacking" configuration +section. + +timer_stats collects information about the timer events which are fired in a +Linux system over a sample period: + +- the pid of the task(process) which initialized the timer +- the name of the process which initialized the timer +- the function where the timer was intialized +- the callback function which is associated to the timer +- the number of events (callbacks) + +timer_stats adds an entry to /proc: /proc/timer_stats + +This entry is used to control the statistics functionality and to read out the +sampled information. + +The timer_stats functionality is inactive on bootup. + +To activate a sample period issue: +# echo 1 >/proc/timer_stats + +To stop a sample period issue: +# echo 0 >/proc/timer_stats + +The statistics can be retrieved by: +# cat /proc/timer_stats + +The readout of /proc/timer_stats automatically disables sampling. The sampled +information is kept until a new sample period is started. This allows multiple +readouts. + +Sample output of /proc/timer_stats: + +Timerstats sample period: 3.888770 s + 12, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) + 15, 1 swapper hcd_submit_urb (rh_timer_func) + 4, 959 kedac schedule_timeout (process_timeout) + 1, 0 swapper page_writeback_init (wb_timer_fn) + 28, 0 swapper hrtimer_stop_sched_tick (hrtimer_sched_tick) + 22, 2948 IRQ 4 tty_flip_buffer_push (delayed_work_timer_fn) + 3, 3100 bash schedule_timeout (process_timeout) + 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) + 1, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) + 1, 1 swapper neigh_table_init_no_netlink (neigh_periodic_timer) + 1, 2292 ip __netdev_watchdog_up (dev_watchdog) + 1, 23 events/1 do_cache_clean (delayed_work_timer_fn) +90 total events, 30.0 events/sec + +The first column is the number of events, the second column the pid, the third +column is the name of the process. The forth column shows the function which +initialized the timer and in parantheses the callback function which was +executed on expiry. + + Thomas, Ingo + +Added flag to indicate 'deferrable timer' in /proc/timer_stats. A deferrable +timer will appear as follows + 10D, 1 swapper queue_delayed_work_on (delayed_work_timer_fn) + -- cgit v1.2.3 From 00d1c5e05736f947687be27706bda01cec104e57 Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 17 Apr 2008 17:40:45 +0200 Subject: x86: add gbpages switches These new controls toggle experimental support for a new CPU feature, the straightforward extension of largepages from the pmd level to the pud level, which allows 1GB (kernel) TLBs instead of 2MB TLBs. Turn it off by default, as this code has not been tested well enough yet. Use the CONFIG_DIRECT_GBPAGES=y .config option or gbpages on the boot line can be used to enable it. If enabled in the .config then nogbpages boot option disables it. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- Documentation/x86_64/boot-options.txt | 5 +++++ arch/x86/Kconfig.debug | 12 ++++++++++++ arch/x86/mm/init_64.c | 20 ++++++++++++++++++++ include/asm-x86/pgtable_64.h | 2 ++ 4 files changed, 39 insertions(+) (limited to 'Documentation') diff --git a/Documentation/x86_64/boot-options.txt b/Documentation/x86_64/boot-options.txt index 34abae4e9442..b0c7b6c4abda 100644 --- a/Documentation/x86_64/boot-options.txt +++ b/Documentation/x86_64/boot-options.txt @@ -307,3 +307,8 @@ Debugging stuck (default) Miscellaneous + + nogbpages + Do not use GB pages for kernel direct mappings. + gbpages + Use GB pages for kernel direct mappings. diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug index 7ce8e7025661..f4413c04e687 100644 --- a/arch/x86/Kconfig.debug +++ b/arch/x86/Kconfig.debug @@ -76,6 +76,18 @@ config DEBUG_RODATA data. This is recommended so that we can catch kernel bugs sooner. If in doubt, say "Y". +config DIRECT_GBPAGES + bool "Enable gbpages-mapped kernel pagetables" + depends on DEBUG_KERNEL && EXPERIMENTAL && X86_64 + help + Enable gigabyte pages support (if the CPU supports it). This can + improve the kernel's performance a tiny bit by reducing TLB + pressure. + + This is experimental code. + + If in doubt, say "N". + config DEBUG_RODATA_TEST bool "Testcase for the DEBUG_RODATA feature" depends on DEBUG_RODATA diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index a02a14f0f324..6e7d5a42a09a 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -54,6 +54,26 @@ static unsigned long dma_reserve __initdata; DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); +int direct_gbpages __meminitdata +#ifdef CONFIG_DIRECT_GBPAGES + = 1 +#endif +; + +static int __init parse_direct_gbpages_off(char *arg) +{ + direct_gbpages = 0; + return 0; +} +early_param("nogbpages", parse_direct_gbpages_off); + +static int __init parse_direct_gbpages_on(char *arg) +{ + direct_gbpages = 1; + return 0; +} +early_param("gbpages", parse_direct_gbpages_on); + /* * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the * physical space so we can cache the place of the first one and move diff --git a/include/asm-x86/pgtable_64.h b/include/asm-x86/pgtable_64.h index 01d2359e7a34..6ef09914acbe 100644 --- a/include/asm-x86/pgtable_64.h +++ b/include/asm-x86/pgtable_64.h @@ -239,6 +239,8 @@ static inline int pud_large(pud_t pte) #define update_mmu_cache(vma,address,pte) do { } while (0) +extern int direct_gbpages; + /* Encode and de-code a swap entry */ #define __swp_type(x) (((x).val >> 1) & 0x3f) #define __swp_offset(x) ((x).val >> 8) -- cgit v1.2.3 From 099e1377269a47ed30a00ee131001988e5bcaa9c Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Wed, 13 Feb 2008 20:54:58 +0000 Subject: x86: use ELF format in compressed images. Signed-off-by: Ian Campbell Cc: Ian Campbell Cc: Jeremy Fitzhardinge Cc: virtualization@lists.linux-foundation.org Cc: H. Peter Anvin Cc: Jeremy Fitzhardinge Cc: virtualization@lists.linux-foundation.org Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- Documentation/i386/boot.txt | 18 +++++++++++++ arch/x86/boot/Makefile | 14 ++++++++++ arch/x86/boot/compressed/Makefile | 2 +- arch/x86/boot/compressed/misc.c | 56 +++++++++++++++++++++++++++++++++++++++ arch/x86/boot/header.S | 6 +++++ 5 files changed, 95 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt index fc49b79bc1ab..b5f5ba1ea668 100644 --- a/Documentation/i386/boot.txt +++ b/Documentation/i386/boot.txt @@ -170,6 +170,8 @@ Offset Proto Name Meaning 0238/4 2.06+ cmdline_size Maximum size of the kernel command line 023C/4 2.07+ hardware_subarch Hardware subarchitecture 0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data +0248/4 2.08+ compressed_payload_offset +024C/4 2.08+ compressed_payload_length (1) For backwards compatibility, if the setup_sects field contains 0, the real value is 4. @@ -512,6 +514,22 @@ Protocol: 2.07+ A pointer to data that is specific to hardware subarch +Field name: compressed_payload_offset +Type: read +Offset/size: 0x248/4 +Protocol: 2.08+ + + If non-zero then this field contains the offset from the end of the + real-mode code to the compressed payload. The compression format + should be determined using the standard magic number, currently only + gzip is used. + +Field name: compressed_payload_length +Type: read +Offset/size: 0x24c/4 +Protocol: 2.08+ + + The length of the compressed payload. **** THE KERNEL COMMAND LINE diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile index f88458e83ef0..9695affeb584 100644 --- a/arch/x86/boot/Makefile +++ b/arch/x86/boot/Makefile @@ -94,6 +94,20 @@ $(obj)/vmlinux.bin: $(obj)/compressed/vmlinux FORCE SETUP_OBJS = $(addprefix $(obj)/,$(setup-y)) +sed-offsets := -e 's/^00*/0/' \ + -e 's/^\([0-9a-fA-F]*\) . \(input_data\|input_data_end\)$$/\#define \2 0x\1/p' + +quiet_cmd_offsets = OFFSETS $@ + cmd_offsets = $(NM) $< | sed -n $(sed-offsets) > $@ + +$(obj)/offsets.h: $(obj)/compressed/vmlinux FORCE + $(call if_changed,offsets) + +targets += offsets.h + +AFLAGS_header.o += -I$(obj) +$(obj)/header.o: $(obj)/offsets.h + LDFLAGS_setup.elf := -T $(obj)/setup.elf: $(src)/setup.ld $(SETUP_OBJS) FORCE $(call if_changed,ld) diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile index d2b9f3bb87c0..92fdd35bd93e 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -22,7 +22,7 @@ $(obj)/vmlinux: $(src)/vmlinux_$(BITS).lds $(obj)/head_$(BITS).o $(obj)/misc.o $ $(call if_changed,ld) @: -OBJCOPYFLAGS_vmlinux.bin := -O binary -R .note -R .comment -S +OBJCOPYFLAGS_vmlinux.bin := -R .comment -S $(obj)/vmlinux.bin: vmlinux FORCE $(call if_changed,objcopy) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 8182e32c1b42..69aec2f4155d 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -15,6 +15,10 @@ * we just keep it from happening */ #undef CONFIG_PARAVIRT +#ifdef CONFIG_X86_32 +#define _ASM_DESC_H_ 1 +#endif + #ifdef CONFIG_X86_64 #define _LINUX_STRING_H_ 1 #define __LINUX_BITMAP_H 1 @@ -22,6 +26,7 @@ #include #include +#include #include #include #include @@ -365,6 +370,56 @@ static void error(char *x) asm("hlt"); } +static void parse_elf(void *output) +{ +#ifdef CONFIG_X86_64 + Elf64_Ehdr ehdr; + Elf64_Phdr *phdrs, *phdr; +#else + Elf32_Ehdr ehdr; + Elf32_Phdr *phdrs, *phdr; +#endif + void *dest; + int i; + + memcpy(&ehdr, output, sizeof(ehdr)); + if(ehdr.e_ident[EI_MAG0] != ELFMAG0 || + ehdr.e_ident[EI_MAG1] != ELFMAG1 || + ehdr.e_ident[EI_MAG2] != ELFMAG2 || + ehdr.e_ident[EI_MAG3] != ELFMAG3) + { + error("Kernel is not a valid ELF file"); + return; + } + + putstr("Parsing ELF... "); + + phdrs = malloc(sizeof(*phdrs) * ehdr.e_phnum); + if (!phdrs) + error("Failed to allocate space for phdrs"); + + memcpy(phdrs, output + ehdr.e_phoff, sizeof(*phdrs) * ehdr.e_phnum); + + for (i=0; ip_type) { + case PT_LOAD: +#ifdef CONFIG_RELOCATABLE + dest = output; + dest += (phdr->p_paddr - LOAD_PHYSICAL_ADDR); +#else + dest = (void*)(phdr->p_paddr); +#endif + memcpy(dest, + output + phdr->p_offset, + phdr->p_filesz); + break; + default: /* Ignore other PT_* */ break; + } + } +} + asmlinkage void decompress_kernel(void *rmode, memptr heap, uch *input_data, unsigned long input_len, uch *output) @@ -408,6 +463,7 @@ asmlinkage void decompress_kernel(void *rmode, memptr heap, makecrc(); putstr("\nDecompressing Linux... "); gunzip(); + parse_elf(output); putstr("done.\nBooting the kernel.\n"); return; } diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 64ad9016585a..8471658d5534 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -22,6 +22,7 @@ #include #include #include "boot.h" +#include "offsets.h" SETUPSECTS = 4 /* default nr of setup-sectors */ BOOTSEG = 0x07C0 /* original address of boot-sector */ @@ -223,6 +224,11 @@ hardware_subarch: .long 0 # subarchitecture, added with 2.07 hardware_subarch_data: .quad 0 +compressed_payload_offset: + .long input_data +compressed_payload_length: + .long input_data_end-input_data + # End of setup header ##################################################### .section ".inittext", "ax" -- cgit v1.2.3 From 7d6e737c8d2698b63ad10fd75cc6793380395d0e Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Sun, 17 Feb 2008 20:06:35 +0100 Subject: x86: add a crc32 checksum to the kernel image. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- Documentation/i386/boot.txt | 8 +++++ arch/x86/boot/tools/build.c | 88 ++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt index b5f5ba1ea668..05c24dfd7ecf 100644 --- a/Documentation/i386/boot.txt +++ b/Documentation/i386/boot.txt @@ -531,6 +531,14 @@ Protocol: 2.08+ The length of the compressed payload. +**** THE IMAGE CHECKSUM + +From boot protocol version 2.08 onwards the CRC-32 is calculated over +the entire file using the characteristic polynomial 0x04C11DB7 and an +initial remainder of 0xffffffff. The checksum is appended to the +file; therefore the CRC of the file up to the limit specified in the +syssize field of the header is always 0. + **** THE KERNEL COMMAND LINE The kernel command line has become an important way for the boot diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c index b4248740ff0d..44dc1923c0e3 100644 --- a/arch/x86/boot/tools/build.c +++ b/arch/x86/boot/tools/build.c @@ -50,6 +50,75 @@ typedef unsigned long u32; u8 buf[SETUP_SECT_MAX*512]; int is_big_kernel; +/*----------------------------------------------------------------------*/ + +static const u32 crctab32[] = { + 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 u32 partial_crc32_one(u8 c, u32 crc) +{ + return crctab32[(crc ^ c) & 0xff] ^ (crc >> 8); +} + +static u32 partial_crc32(const u8 *s, int len, u32 crc) +{ + while (len--) + crc = partial_crc32_one(*s++, crc); + return crc; +} + static void die(const char * str, ...) { va_list args; @@ -74,6 +143,7 @@ int main(int argc, char ** argv) FILE *file; int fd; void *kernel; + u32 crc = 0xffffffffUL; if (argc > 2 && !strcmp(argv[1], "-b")) { @@ -144,7 +214,8 @@ int main(int argc, char ** argv) kernel = mmap(NULL, sz, PROT_READ, MAP_SHARED, fd, 0); if (kernel == MAP_FAILED) die("Unable to mmap '%s': %m", argv[2]); - sys_size = (sz + 15) / 16; + /* Number of 16-byte paragraphs, including space for a 4-byte CRC */ + sys_size = (sz + 15 + 4) / 16; if (!is_big_kernel && sys_size > DEF_SYSSIZE) die("System is too big. Try using bzImage or modules."); @@ -155,12 +226,27 @@ int main(int argc, char ** argv) buf[0x1f6] = sys_size >> 16; buf[0x1f7] = sys_size >> 24; + crc = partial_crc32(buf, i, crc); if (fwrite(buf, 1, i, stdout) != i) die("Writing setup failed"); /* Copy the kernel code */ + crc = partial_crc32(kernel, sz, crc); if (fwrite(kernel, 1, sz, stdout) != sz) die("Writing kernel failed"); + + /* Add padding leaving 4 bytes for the checksum */ + while (sz++ < (sys_size*16) - 4) { + crc = partial_crc32_one('\0', crc); + if (fwrite("\0", 1, 1, stdout) != 1) + die("Writing padding failed"); + } + + /* Write the CRC */ + fprintf(stderr, "CRC %lx\n", crc); + if (fwrite(&crc, 1, 4, stdout) != 4) + die("Writing CRC failed"); + close(fd); /* Everything is OK */ -- cgit v1.2.3 From 87253d1b4f2b5a29bdfc6275b9fb52a47d72df64 Mon Sep 17 00:00:00 2001 From: Ian Campbell Date: Tue, 19 Feb 2008 11:12:30 +0000 Subject: x86: boot protocol updates Also update field names to simply payload_{offset,length} so as to not rule out uncompressed images. Signed-off-by: Ian Campbell Cc: H. Peter Anvin Cc: Jeremy Fitzhardinge Cc: virtualization@lists.linux-foundation.org Signed-off-by: Ingo Molnar --- Documentation/i386/boot.txt | 18 ++++++++++-------- arch/x86/boot/header.S | 6 ++---- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt index 05c24dfd7ecf..2eb16100bb3f 100644 --- a/Documentation/i386/boot.txt +++ b/Documentation/i386/boot.txt @@ -170,8 +170,8 @@ Offset Proto Name Meaning 0238/4 2.06+ cmdline_size Maximum size of the kernel command line 023C/4 2.07+ hardware_subarch Hardware subarchitecture 0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data -0248/4 2.08+ compressed_payload_offset -024C/4 2.08+ compressed_payload_length +0248/4 2.08+ payload_offset Offset of kernel payload +024C/4 2.08+ payload_length Length of kernel payload (1) For backwards compatibility, if the setup_sects field contains 0, the real value is 4. @@ -514,22 +514,24 @@ Protocol: 2.07+ A pointer to data that is specific to hardware subarch -Field name: compressed_payload_offset +Field name: payload_offset Type: read Offset/size: 0x248/4 Protocol: 2.08+ If non-zero then this field contains the offset from the end of the - real-mode code to the compressed payload. The compression format - should be determined using the standard magic number, currently only - gzip is used. + real-mode code to the payload. + + The payload may be compressed. The format of both the compressed and + uncompressed data should be determined using the standard magic + numbers. Currently only gzip compressed ELF is used. -Field name: compressed_payload_length +Field name: payload_length Type: read Offset/size: 0x24c/4 Protocol: 2.08+ - The length of the compressed payload. + The length of the payload. **** THE IMAGE CHECKSUM diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S index 40c91bb483e1..6d2df8d61c54 100644 --- a/arch/x86/boot/header.S +++ b/arch/x86/boot/header.S @@ -224,10 +224,8 @@ hardware_subarch: .long 0 # subarchitecture, added with 2.07 hardware_subarch_data: .quad 0 -compressed_payload_offset: - .long input_data -compressed_payload_length: - .long input_data_end-input_data +payload_offset: .long input_data +payload_length: .long input_data_end-input_data # End of setup header ##################################################### -- cgit v1.2.3 From b552da8740222c35bcd83c9be7b27185bfb6d53c Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Wed, 19 Mar 2008 15:58:11 +0100 Subject: x86 iommu: add more documentation Fix coding style in pci-dma_64.c and add stubs for documentation. I hope someone fills the rest, I understand maybe off and soft... Signed-off-by: Pavel Machek Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 13 +++++++++++++ arch/x86/kernel/pci-dma_64.c | 20 ++++++++++---------- 2 files changed, 23 insertions(+), 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index dafd001bf833..43c527d72f2f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -812,6 +812,19 @@ and is between 256 and 4096 characters. It is defined in the file inttest= [IA64] + iommu= [x86] + off + force + noforce + biomerge + panic + nopanic + merge + nomerge + forcesac + soft + + intel_iommu= [DMAR] Intel IOMMU driver (DMAR) option off Disable intel iommu driver. diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index 375cb2bc45be..ada5a0604992 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -232,32 +232,32 @@ static __init int iommu_setup(char *p) return -EINVAL; while (*p) { - if (!strncmp(p,"off",3)) + if (!strncmp(p, "off", 3)) no_iommu = 1; /* gart_parse_options has more force support */ - if (!strncmp(p,"force",5)) + if (!strncmp(p, "force", 5)) force_iommu = 1; - if (!strncmp(p,"noforce",7)) { + if (!strncmp(p, "noforce", 7)) { iommu_merge = 0; force_iommu = 0; } - if (!strncmp(p, "biomerge",8)) { + if (!strncmp(p, "biomerge", 8)) { iommu_bio_merge = 4096; iommu_merge = 1; force_iommu = 1; } - if (!strncmp(p, "panic",5)) + if (!strncmp(p, "panic", 5)) panic_on_overflow = 1; - if (!strncmp(p, "nopanic",7)) + if (!strncmp(p, "nopanic", 7)) panic_on_overflow = 0; - if (!strncmp(p, "merge",5)) { + if (!strncmp(p, "merge", 5)) { iommu_merge = 1; force_iommu = 1; } - if (!strncmp(p, "nomerge",7)) + if (!strncmp(p, "nomerge", 7)) iommu_merge = 0; - if (!strncmp(p, "forcesac",8)) + if (!strncmp(p, "forcesac", 8)) iommu_sac_force = 1; if (!strncmp(p, "allowdac", 8)) forbid_dac = 0; @@ -265,7 +265,7 @@ static __init int iommu_setup(char *p) forbid_dac = -1; #ifdef CONFIG_SWIOTLB - if (!strncmp(p, "soft",4)) + if (!strncmp(p, "soft", 4)) swiotlb = 1; #endif -- cgit v1.2.3 From d27554d874c7eeb14c8bfecdc39c3a8618cd8d32 Mon Sep 17 00:00:00 2001 From: "venkatesh.pallipadi@intel.com" Date: Tue, 18 Mar 2008 17:00:13 -0700 Subject: x86: PAT documentation Documentation about PAT related interfaces, intended usage and memory attribute relationship. Signed-off-by: Venkatesh Pallipadi Signed-off-by: Suresh Siddha Signed-off-by: Ingo Molnar --- Documentation/x86/pat.txt | 100 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 Documentation/x86/pat.txt (limited to 'Documentation') diff --git a/Documentation/x86/pat.txt b/Documentation/x86/pat.txt new file mode 100644 index 000000000000..17965f927c15 --- /dev/null +++ b/Documentation/x86/pat.txt @@ -0,0 +1,100 @@ + +PAT (Page Attribute Table) + +x86 Page Attribute Table (PAT) allows for setting the memory attribute at the +page level granularity. PAT is complementary to the MTRR settings which allows +for setting of memory types over physical address ranges. However, PAT is +more flexible than MTRR due to its capability to set attributes at page level +and also due to the fact that there are no hardware limitations on number of +such attribute settings allowed. Added flexibility comes with guidelines for +not having memory type aliasing for the same physical memory with multiple +virtual addresses. + +PAT allows for different types of memory attributes. The most commonly used +ones that will be supported at this time are Write-back, Uncached, +Write-combined and Uncached Minus. + +There are many different APIs in the kernel that allows setting of memory +attributes at the page level. In order to avoid aliasing, these interfaces +should be used thoughtfully. Below is a table of interfaces available, +their intended usage and their memory attribute relationships. Internally, +these APIs use a reserve_memtype()/free_memtype() interface on the physical +address range to avoid any aliasing. + + +------------------------------------------------------------------- +API | RAM | ACPI,... | Reserved/Holes | +-----------------------|----------|------------|------------------| + | | | | +ioremap | -- | UC | UC | + | | | | +ioremap_cache | -- | WB | WB | + | | | | +ioremap_nocache | -- | UC | UC | + | | | | +ioremap_wc | -- | -- | WC | + | | | | +set_memory_uc | UC | -- | -- | + set_memory_wb | | | | + | | | | +set_memory_wc | WC | -- | -- | + set_memory_wb | | | | + | | | | +pci sysfs resource | -- | -- | UC | + | | | | +pci sysfs resource_wc | -- | -- | WC | + is IORESOURCE_PREFETCH| | | | + | | | | +pci proc | -- | -- | UC | + !PCIIOC_WRITE_COMBINE | | | | + | | | | +pci proc | -- | -- | WC | + PCIIOC_WRITE_COMBINE | | | | + | | | | +/dev/mem | -- | UC | UC | + read-write | | | | + | | | | +/dev/mem | -- | UC | UC | + mmap SYNC flag | | | | + | | | | +/dev/mem | -- | WB/WC/UC | WB/WC/UC | + mmap !SYNC flag | |(from exist-| (from exist- | + and | | ing alias)| ing alias) | + any alias to this area| | | | + | | | | +/dev/mem | -- | WB | WB | + mmap !SYNC flag | | | | + no alias to this area | | | | + and | | | | + MTRR says WB | | | | + | | | | +/dev/mem | -- | -- | UC_MINUS | + mmap !SYNC flag | | | | + no alias to this area | | | | + and | | | | + MTRR says !WB | | | | + | | | | +------------------------------------------------------------------- + +Notes: + +-- in the above table mean "Not suggested usage for the API". Some of the --'s +are strictly enforced by the kernel. Some others are not really enforced +today, but may be enforced in future. + +For ioremap and pci access through /sys or /proc - The actual type returned +can be more restrictive, in case of any existing aliasing for that address. +For example: If there is an existing uncached mapping, a new ioremap_wc can +return uncached mapping in place of write-combine requested. + +set_memory_[uc|wc] and set_memory_wb should be used in pairs, where driver will +first make a region uc or wc and switch it back to wb after use. + +Over time writes to /proc/mtrr will be deprecated in favor of using PAT based +interfaces. Users writing to /proc/mtrr are suggested to use above interfaces. + +Drivers should use ioremap_[uc|wc] to access PCI BARs with [uc|wc] access +types. + +Drivers should use set_memory_[uc|wc] to set access type for RAM ranges. + -- cgit v1.2.3 From c64df70793a9c344874eb4af19f85e0662d2d3ee Mon Sep 17 00:00:00 2001 From: Yinghai Lu Date: Fri, 21 Mar 2008 18:56:19 -0700 Subject: x86: memtest bootparam Signed-off-by: Yinghai Lu Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 5 +++++ arch/x86/Kconfig | 29 +++++++++++++++++++++++++++++ arch/x86/kernel/e820_64.c | 10 +++++----- arch/x86/mm/init_64.c | 24 +++++++++++++++++------- 4 files changed, 56 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 43c527d72f2f..f9ea0803d5d6 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1147,6 +1147,11 @@ and is between 256 and 4096 characters. It is defined in the file or memmap=0x10000$0x18690000 + memtest= [KNL,X86_64] Enable memtest + Format: + range: 0,4 : pattern number + default : 0 + meye.*= [HW] Set MotionEye Camera parameters See Documentation/video4linux/meye.txt. diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index e50e38e76d9f..a0d7406e8b37 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -382,6 +382,35 @@ config PARAVIRT endif +config MEMTEST_BOOTPARAM + bool "Memtest boot parameter" + depends on X86_64 + default y + help + This option adds a kernel parameter 'memtest', which allows memtest + to be disabled at boot. If this option is selected, memtest + functionality can be disabled with memtest=0 on the kernel + command line. The purpose of this option is to allow a single + kernel image to be distributed with memtest built in, but not + necessarily enabled. + + If you are unsure how to answer this question, answer Y. + +config MEMTEST_BOOTPARAM_VALUE + int "Memtest boot parameter default value (0-4)" + depends on MEMTEST_BOOTPARAM + range 0 4 + default 0 + help + This option sets the default value for the kernel parameter + 'memtest', which allows memtest to be disabled at boot. If this + option is set to 0 (zero), the memtest kernel parameter will + default to 0, disabling memtest at bootup. If this option is + set to 4, the memtest kernel parameter will default to 4, + enabling memtest at bootup, and use that as pattern number. + + If you are unsure how to answer this question, answer 0. + config ACPI_SRAT def_bool y depends on X86_32 && ACPI && NUMA && (X86_SUMMIT || X86_GENERICARCH) diff --git a/arch/x86/kernel/e820_64.c b/arch/x86/kernel/e820_64.c index 9184e6437c4f..d6ada0833876 100644 --- a/arch/x86/kernel/e820_64.c +++ b/arch/x86/kernel/e820_64.c @@ -241,7 +241,9 @@ unsigned long __init find_e820_area(unsigned long start, unsigned long end, /* * Find next free range after *start */ -unsigned long __init find_e820_area_size(unsigned long start, unsigned long *sizep, unsigned long align) +unsigned long __init find_e820_area_size(unsigned long start, + unsigned long *sizep, + unsigned long align) { int i; @@ -254,17 +256,15 @@ unsigned long __init find_e820_area_size(unsigned long start, unsigned long *siz continue; addr = round_up(ei->addr, align); ei_last = ei->addr + ei->size; -// printk(KERN_DEBUG "find_e820_area_size : e820 %d [%llx, %lx]\n", i, ei->addr, ei_last); if (addr < start) addr = round_up(start, align); -// printk(KERN_DEBUG "find_e820_area_size : 0 [%lx, %lx]\n", addr, ei_last); if (addr >= ei_last) continue; *sizep = ei_last - addr; - while (bad_addr_size(&addr, sizep, align) && addr+ *sizep <= ei_last) + while (bad_addr_size(&addr, sizep, align) && + addr + *sizep <= ei_last) ; last = addr + *sizep; -// printk(KERN_DEBUG "find_e820_area_size : 1 [%lx, %lx]\n", addr, last); if (last > ei_last) continue; return addr; diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 52f54ee4559f..ae225c3ae9a8 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -427,7 +427,10 @@ static void __init init_gbpages(void) direct_gbpages = 0; } -static void __init memtest(unsigned long start_phys, unsigned long size, unsigned pattern) +#ifdef CONFIG_MEMTEST_BOOTPARAM + +static void __init memtest(unsigned long start_phys, unsigned long size, + unsigned pattern) { unsigned long i; unsigned long *start; @@ -486,11 +489,12 @@ static void __init memtest(unsigned long start_phys, unsigned long size, unsigne } -static int __initdata memtest_pattern; +static int memtest_pattern __initdata = CONFIG_MEMTEST_BOOTPARAM_VALUE; + static int __init parse_memtest(char *arg) { if (arg) - memtest_pattern = simple_strtoul(arg, NULL, 0) + 1; + memtest_pattern = simple_strtoul(arg, NULL, 0); return 0; } @@ -501,8 +505,10 @@ static void __init early_memtest(unsigned long start, unsigned long end) unsigned long t_start, t_size; unsigned pattern; - if (memtest_pattern) - printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern); + if (!memtest_pattern) + return; + + printk(KERN_INFO "early_memtest: pattern num %d", memtest_pattern); for (pattern = 0; pattern < memtest_pattern; pattern++) { t_start = start; t_size = 0; @@ -523,9 +529,13 @@ static void __init early_memtest(unsigned long start, unsigned long end) t_start += t_size; } } - if (memtest_pattern) - printk(KERN_CONT "\n"); + printk(KERN_CONT "\n"); } +#else +static void __init early_memtest(unsigned long start, unsigned long end) +{ +} +#endif /* * Setup the direct mapping of the physical memory at PAGE_OFFSET. -- cgit v1.2.3 From 19b4e7f4e9b1c88459cf2c9b9ccaa09cb8bf854d Mon Sep 17 00:00:00 2001 From: Ingo Molnar Date: Thu, 10 Apr 2008 10:12:27 +0200 Subject: x86: extend the scheduled bzImage symlinks removal use of the bzImage symlinks in developer scripts is still widespread, so lets extend the removal period by 2 years. These symlinks cost us near nothing. Signed-off-by: Ingo Molnar --- Documentation/feature-removal-schedule.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index bf0e3df8e7a1..164c89394cff 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -212,7 +212,7 @@ Who: Stephen Hemminger --------------------------- What: i386/x86_64 bzImage symlinks -When: April 2008 +When: April 2010 Why: The i386/x86_64 merge provides a symlink to the old bzImage location so not yet updated user space tools, e.g. package -- cgit v1.2.3 From 6cdf6e06d70dcf42314edb2c43b7c7ebc56e32e5 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Thu, 17 Apr 2008 20:05:38 +0200 Subject: kgdb: document parameters document the kgdboc module/boot parameter. Signed-off-by: Jason Wessel Signed-off-by: Jan Kiszka Signed-off-by: Ingo Molnar --- Documentation/kernel-parameters.txt | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index dafd001bf833..c3de1767edd4 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -928,6 +928,11 @@ and is between 256 and 4096 characters. It is defined in the file kstack=N [X86-32,X86-64] Print N words from the kernel stack in oops dumps. + kgdboc= [HW] kgdb over consoles. + Requires a tty driver that supports console polling. + (only serial suported for now) + Format: [,baud] + l2cr= [PPC] lapic [X86-32,APIC] Enable the local APIC even if BIOS -- cgit v1.2.3 From e3e2aaf7dc0d82a055e084cfd48b9257c0c66b68 Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Thu, 20 Mar 2008 13:43:45 -0500 Subject: kgdb: add documentation Add in the kgdb documentation for kgdb. Signed-off-by: Jason Wessel Signed-off-by: Ingo Molnar --- Documentation/DocBook/Makefile | 2 +- Documentation/DocBook/kgdb.tmpl | 435 ++++++++++++++++++++++++++++++++++++++++ MAINTAINERS | 6 + include/linux/kgdb.h | 52 +++-- 4 files changed, 473 insertions(+), 22 deletions(-) create mode 100644 Documentation/DocBook/kgdb.tmpl (limited to 'Documentation') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index 300e1707893f..e471bc466a7e 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -9,7 +9,7 @@ DOCBOOKS := wanbook.xml z8530book.xml mcabook.xml videobook.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml networking.xml \ - kernel-api.xml filesystems.xml lsm.xml usb.xml \ + kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl new file mode 100644 index 000000000000..95e5f84cbf56 --- /dev/null +++ b/Documentation/DocBook/kgdb.tmpl @@ -0,0 +1,435 @@ + + + + + + Using kgdb and the kgdb Internals + + + + Jason + Wessel + +
+ jason.wessel@windriver.com +
+
+
+
+ + + + Tom + Rini + +
+ trini@kernel.crashing.org +
+
+
+
+ + + + Amit S. + Kale + +
+ amitkale@linsyssoft.com +
+
+
+
+ + + 2008 + Wind River Systems, Inc. + + + 2004-2005 + MontaVista Software, Inc. + + + 2004 + Amit S. Kale + + + + + This file is licensed under the terms of the GNU General Public License + version 2. This program is licensed "as is" without any warranty of any + kind, whether express or implied. + + + +
+ + + + Introduction + + kgdb is a source level debugger for linux kernel. It is used along + with gdb to debug a linux kernel. The expectation is that gdb can + be used to "break in" to the kernel to inspect memory, variables + and look through a cal stack information similar to what an + application developer would use gdb for. It is possible to place + breakpoints in kernel code and perform some limited execution + stepping. + + + Two machines are required for using kgdb. One of these machines is a + development machine and the other is a test machine. The kernel + to be debugged runs on the test machine. The development machine + runs an instance of gdb against the vmlinux file which contains + the symbols (not boot image such as bzImage, zImage, uImage...). + In gdb the developer specifies the connection parameters and + connects to kgdb. Depending on which kgdb I/O modules exist in + the kernel for a given architecture, it may be possible to debug + the test machine's kernel with the development machine using a + rs232 or ethernet connection. + + + + Compiling a kernel + + To enable CONFIG_KGDB, look under the "Kernel debugging" + and then select "KGDB: kernel debugging with remote gdb". + + + Next you should choose one of more I/O drivers to interconnect debugging + host and debugged target. Early boot debugging requires a KGDB + I/O driver that supports early debugging and the driver must be + built into the kernel directly. Kgdb I/O driver configuration + takes place via kernel or module parameters, see following + chapter. + + + The kgdb test compile options are described in the kgdb test suite chapter. + + + + + Enable kgdb for debugging + + In order to use kgdb you must activate it by passing configuration + information to one of the kgdb I/O drivers. If you do not pass any + configuration information kgdb will not do anything at all. Kgdb + will only actively hook up to the kernel trap hooks if a kgdb I/O + driver is loaded and configured. If you unconfigure a kgdb I/O + driver, kgdb will unregister all the kernel hook points. + + + All drivers can be reconfigured at run time, if + CONFIG_SYSFS and CONFIG_MODULES + are enabled, by echo'ing a new config string to + /sys/module/<driver>/parameter/<option>. + The driver can be unconfigured by passing an empty string. You cannot + change the configuration while the debugger is attached. Make sure + to detach the debugger with the detach command + prior to trying unconfigure a kgdb I/O driver. + + + Kernel parameter: kgdbwait + + The Kernel command line option kgdbwait makes + kgdb wait for a debugger connection during booting of a kernel. You + can only use this option you compiled a kgdb I/O driver into the + kernel and you specified the I/O driver configuration as a kernel + command line option. The kgdbwait parameter should always follow the + configuration parameter for the kgdb I/O driver in the kernel + command line else the I/O driver will not be configured prior to + asking the kernel to use it to wait. + + + The kernel will stop and wait as early as the I/O driver and + architecture will allow when you use this option. If you build the + kgdb I/O driver as a kernel module kgdbwait will not do anything. + + + + Kernel parameter: kgdboc + + The kgdboc driver was originally an abbreviation meant to stand for + "kgdb over console". Kgdboc is designed to work with a single + serial port as example, and it was meant to cover the circumstance + where you wanted to use a serial console as your primary console as + well as using it to perform kernel debugging. + + + Using kgdboc + + You can configure kgdboc via sysfs or a module or kernel boot line + parameter depending on if you build with CONFIG_KGDBOC as a module + or built-in. + + From the module load or build-in + kgdboc=<tty-device>,[baud] + + The example here would be if your console port was typically ttyS0, you would use something like kgdboc=ttyS0,115200 or on the ARM Versatile AB you would likely use kgdboc=ttyAMA0,115200 + + + From sysfs + echo ttyS0 > /sys/module/kgdboc/parameters/kgdboc + + + + + NOTE: Kgdboc does not support interrupting the target via the + gdb remote protocol. You must manually send a sysrq-g unless you + have a proxy that splits console output to a terminal problem and + has a separate port for the debugger to connect to that sends the + sysrq-g for you. + + When using kgdboc with no debugger proxy, you can end up + connecting the debugger for one of two entry points. If an + exception occurs after you have loaded kgdboc a message should print + on the console stating it is waiting for the debugger. In case you + disconnect your terminal program and then connect the debugger in + its place. If you want to interrupt the target system and forcibly + enter a debug session you have to issue a Sysrq sequence and then + type the letter g. Then you disconnect the + terminal session and connect gdb. Your options if you don't like + this are to hack gdb to send the sysrq-g for you as well as on the + initial connect, or to use a debugger proxy that allows an + unmodified gdb to do the debugging. + + + + kgdboc internals + + The kgdboc driver is actually a very thin driver that relies on the + underlying low level to the hardware driver having "polling hooks" + which the to which the tty driver is attached. In the initial + implementation of kgdboc it the serial_core was changed to expose a + low level uart hook for doing polled mode reading and writing of a + single character while in an atomic context. When kgdb makes an I/O + request to the debugger, kgdboc invokes a call back in the serial + core which in turn uses the call back in the uart driver. It is + certainly possible to extend kgdboc to work with non-uart based + consoles in the future. + + + When using kgdboc with a uart, the uart driver must implement two callbacks in the struct uart_ops. Example from drivers/8250.c: +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = serial8250_get_poll_char, + .poll_put_char = serial8250_put_poll_char, +#endif + + Any implementation specifics around creating a polling driver use the + #ifdef CONFIG_CONSOLE_POLL, as shown above. + Keep in mind that polling hooks have to be implemented in such a way + that they can be called from an atomic context and have to restore + the state of the uart chip on return such that the system can return + to normal when the debugger detaches. You need to be very careful + with any kind of lock you consider, because failing here is most + going to mean pressing the reset button. + + + + + Kernel parameter: kgdbcon + + Kgdb supports using the gdb serial protocol to send console messages + to the debugger when the debugger is connected and running. There + are two ways to activate this feature. + + Activate with the kernel command line option: + kgdbcon + + Use sysfs before configuring an io driver + + echo 1 > /sys/module/kgdb/parameters/kgdb_use_con + + + NOTE: If you do this after you configure the kgdb I/O driver, the + setting will not take effect until the next point the I/O is + reconfigured. + + + + + + IMPORTANT NOTE: Using this option with kgdb over the console + (kgdboc) or kgdb over ethernet (kgdboe) is not supported. + + + + + Connecting gdb + + If you are using kgdboc, you need to have used kgdbwait as a boot + argument, issued a sysrq-g, or the system you are going to debug + has already taken an exception and is waiting for the debugger to + attach before you can connect gdb. + + + If you are not using different kgdb I/O driver other than kgdboc, + you should be able to connect and the target will automatically + respond. + + + Example (using a serial port): + + + % gdb ./vmlinux + (gdb) set remotebaud 115200 + (gdb) target remote /dev/ttyS0 + + + Example (kgdb to a terminal server): + + + % gdb ./vmlinux + (gdb) target remote udp:192.168.2.2:6443 + + + Example (kgdb over ethernet): + + + % gdb ./vmlinux + (gdb) target remote udp:192.168.2.2:6443 + + + Once connected, you can debug a kernel the way you would debug an + application program. + + + If you are having problems connecting or something is going + seriously wrong while debugging, it will most often be the case + that you want to enable gdb to be verbose about its target + communications. You do this prior to issuing the target + remote command by typing in: set remote debug 1 + + + + kgdb Test Suite + + When kgdb is enabled in the kernel config you can also elect to + enable the config parameter KGDB_TESTS. Turning this on will + enable a special kgdb I/O module which is designed to test the + kgdb internal functions. + + + The kgdb tests are mainly intended for developers to test the kgdb + internals as well as a tool for developing a new kgdb architecture + specific implementation. These tests are not really for end users + of the Linux kernel. The primary source of documentation would be + to look in the drivers/misc/kgdbts.c file. + + + The kgdb test suite can also be configured at compile time to run + the core set of tests by setting the kernel config parameter + KGDB_TESTS_ON_BOOT. This particular option is aimed at automated + regression testing and does not require modifying the kernel boot + config arguments. If this is turned on, the kgdb test suite can + be disabled by specifying "kgdbts=" as a kernel boot argument. + + + + Architecture Specifics + + Kgdb is organized into three basic components: + + kgdb core + + The kgdb core is found in kernel/kgdb.c. It contains: + + All the logic to implement the gdb serial protocol + A generic OS exception handler which includes sync'ing the processors into a stopped state on an multi cpu system. + The API to talk to the kgdb I/O drivers + The API to make calls to the arch specific kgdb implementation + The logic to perform safe memory reads and writes to memory while using the debugger + A full implementation for software breakpoints unless overridden by the arch + + + + kgdb arch specific implementation + + This implementation is generally found in arch/*/kernel/kgdb.c. + As an example, arch/x86/kernel/kgdb.c contains the specifics to + implement HW breakpoint as well as the initialization to + dynamically register and unregister for the trap handlers on + this architecture. The arch specific portion implements: + + contains an arch specific trap catcher which + invokes kgdb_handle_exception() to start kgdb about doing its + work + translation to and from gdb specific packet format to pt_regs + Registration and unregistration of architecture specific trap hooks + Any special exception handling and cleanup + NMI exception handling and cleanup + (optional)HW breakpoints + + + + kgdb I/O driver + + Each kgdb I/O driver has to provide an configuration + initialization, and cleanup handler for when it + unloads/unconfigures. Any given kgdb I/O driver has to operate + very closely with the hardware and must do it in such a way that + does not enable interrupts or change other parts of the system + context without completely restoring them. Every kgdb I/O + driver must provide a read and write character interface. The + kgdb core will repeatedly "poll" a kgdb I/O driver for characters + when it needs input. The I/O driver is expected to return + immediately if there is no data available. Doing so allows for + the future possibility to touch watch dog hardware in such a way + as to have a target system not reset when these are enabled. + + + + + + If you are intent on adding kgdb architecture specific support + for a new architecture, the architecture should define + HAVE_ARCH_KGDB in the architecture specific + Kconfig file. This will enable kgdb for the architecture, and + at that point you must create an architecture specific kgdb + implementation. + + + There are a few flags which must be set on every architecture in + their <asm/kgdb.h> file. These are: + + + + NUMREGBYTES: The size in bytes of all of the registers, so + that we can ensure they will all fit into a packet. + + + BUFMAX: The size in bytes of the buffer GDB will read into. + This must be larger than NUMREGBYTES. + + + CACHE_FLUSH_IS_SAFE: Set to 1 if it is always safe to call + flush_cache_range or flush_icache_range. On some architectures, + these functions may not be safe to call on SMP since we keep other + CPUs in a holding pattern. + + + + + + There are also the following functions for the common backend, + found in kernel/kgdb.c, that must be supplied by the + architecture-specific backend unless marked as (optional), in + which case a default function maybe used if the architecture + does not need to provide a specific implementation. + +!Iinclude/linux/kgdb.h + + + Credits + + The following people have contributed to this document: + + Amit Kaleamitkale@linsyssoft.com + Tom Rinitrini@kernel.crashing.org + Jason Wesseljason.wessel@windriver.com + + + +
+ diff --git a/MAINTAINERS b/MAINTAINERS index e46775868019..3eceebb48c92 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -2319,6 +2319,12 @@ L: linux-kernel@vger.kernel.org L: kexec@lists.infradead.org S: Maintained +KGDB +P: Jason Wessel +M: jason.wessel@windriver.com +L: kgdb-bugreport@lists.sourceforge.net +S: Maintained + KPROBES P: Ananth N Mavinakayanahalli M: ananth@in.ibm.com diff --git a/include/linux/kgdb.h b/include/linux/kgdb.h index b0985b79b638..9757b1a6d9dc 100644 --- a/include/linux/kgdb.h +++ b/include/linux/kgdb.h @@ -22,31 +22,34 @@ struct pt_regs; -/* - * kgdb_skipexception - Bail out of KGDB when we've been triggered. +/** + * kgdb_skipexception - (optional) exit kgdb_handle_exception early * @exception: Exception vector number * @regs: Current &struct pt_regs. * - * On some architectures we need to skip a breakpoint exception when - * it occurs after a breakpoint has been removed. + * On some architectures it is required to skip a breakpoint + * exception when it occurs after a breakpoint has been removed. + * This can be implemented in the architecture specific portion of + * for kgdb. */ extern int kgdb_skipexception(int exception, struct pt_regs *regs); -/* - * kgdb_post_primary_code - Save error vector/code numbers. +/** + * kgdb_post_primary_code - (optional) Save error vector/code numbers. * @regs: Original pt_regs. * @e_vector: Original error vector. * @err_code: Original error code. * - * This is needed on architectures which support SMP and KGDB. - * This function is called after all the secondary cpus have been put - * to a know spin state and the primary CPU has control over KGDB. + * This is usually needed on architectures which support SMP and + * KGDB. This function is called after all the secondary cpus have + * been put to a know spin state and the primary CPU has control over + * KGDB. */ extern void kgdb_post_primary_code(struct pt_regs *regs, int e_vector, int err_code); -/* - * kgdb_disable_hw_debug - Disable hardware debugging while we in kgdb. +/** + * kgdb_disable_hw_debug - (optional) Disable hardware debugging hook * @regs: Current &struct pt_regs. * * This function will be called if the particular architecture must @@ -59,7 +62,14 @@ struct tasklet_struct; struct task_struct; struct uart_port; -/* To enter the debugger explicitly. */ +/** + * kgdb_breakpoint - compiled in breakpoint + * + * This will be impelmented a static inline per architecture. This + * function is called by the kgdb core to execute an architecture + * specific trap to cause kgdb to enter the exception processing. + * + */ void kgdb_breakpoint(void); extern int kgdb_connected; @@ -102,7 +112,7 @@ struct kgdb_bkpt { * Functions each KGDB-supporting architecture must provide: */ -/* +/** * kgdb_arch_init - Perform any architecture specific initalization. * * This function will handle the initalization of any architecture @@ -110,7 +120,7 @@ struct kgdb_bkpt { */ extern int kgdb_arch_init(void); -/* +/** * kgdb_arch_exit - Perform any architecture specific uninitalization. * * This function will handle the uninitalization of any architecture @@ -118,7 +128,7 @@ extern int kgdb_arch_init(void); */ extern void kgdb_arch_exit(void); -/* +/** * pt_regs_to_gdb_regs - Convert ptrace regs to GDB regs * @gdb_regs: A pointer to hold the registers in the order GDB wants. * @regs: The &struct pt_regs of the current process. @@ -128,7 +138,7 @@ extern void kgdb_arch_exit(void); */ extern void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs); -/* +/** * sleeping_thread_to_gdb_regs - Convert ptrace regs to GDB regs * @gdb_regs: A pointer to hold the registers in the order GDB wants. * @p: The &struct task_struct of the desired process. @@ -143,7 +153,7 @@ extern void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs); extern void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p); -/* +/** * gdb_regs_to_pt_regs - Convert GDB regs to ptrace regs. * @gdb_regs: A pointer to hold the registers we've received from GDB. * @regs: A pointer to a &struct pt_regs to hold these values in. @@ -153,7 +163,7 @@ sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p); */ extern void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs); -/* +/** * kgdb_arch_handle_exception - Handle architecture specific GDB packets. * @vector: The error vector of the exception that happened. * @signo: The signal number of the exception that happened. @@ -175,7 +185,7 @@ kgdb_arch_handle_exception(int vector, int signo, int err_code, char *remcom_out_buffer, struct pt_regs *regs); -/* +/** * kgdb_roundup_cpus - Get other CPUs into a holding pattern * @flags: Current IRQ state * @@ -198,7 +208,7 @@ extern int kgdb_validate_break_address(unsigned long addr); extern int kgdb_arch_set_breakpoint(unsigned long addr, char *saved_instr); extern int kgdb_arch_remove_breakpoint(unsigned long addr, char *bundle); -/* +/** * struct kgdb_arch - Describe architecture specific values. * @gdb_bpt_instr: The instruction to trigger a breakpoint. * @flags: Flags for the breakpoint, currently just %KGDB_HW_BREAKPOINT. @@ -227,7 +237,7 @@ struct kgdb_arch { void (*correct_hw_break)(void); }; -/* +/** * struct kgdb_io - Describe the interface for an I/O driver to talk with KGDB. * @name: Name of the I/O driver. * @read_char: Pointer to a function that will return one char. -- cgit v1.2.3 From 225a4424ade24e913c081d5a4c4bd71a0fe2e0ac Mon Sep 17 00:00:00 2001 From: Jason Wessel Date: Tue, 1 Apr 2008 16:55:26 -0500 Subject: kgdb: documentation fixes Minor cleanups to kgdb docs. Signed-off-by: Jason Wessel Signed-off-by: Ingo Molnar --- Documentation/DocBook/kgdb.tmpl | 104 ++++++++++++++++++++++------------------ 1 file changed, 58 insertions(+), 46 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/kgdb.tmpl b/Documentation/DocBook/kgdb.tmpl index 95e5f84cbf56..97618bed4d65 100644 --- a/Documentation/DocBook/kgdb.tmpl +++ b/Documentation/DocBook/kgdb.tmpl @@ -152,9 +152,10 @@ The kgdboc driver was originally an abbreviation meant to stand for "kgdb over console". Kgdboc is designed to work with a single - serial port as example, and it was meant to cover the circumstance + serial port. It was meant to cover the circumstance where you wanted to use a serial console as your primary console as - well as using it to perform kernel debugging. + well as using it to perform kernel debugging. Of course you can + also use kgdboc without assigning a console to the same port. Using kgdboc @@ -195,37 +196,6 @@ unmodified gdb to do the debugging. - - kgdboc internals - - The kgdboc driver is actually a very thin driver that relies on the - underlying low level to the hardware driver having "polling hooks" - which the to which the tty driver is attached. In the initial - implementation of kgdboc it the serial_core was changed to expose a - low level uart hook for doing polled mode reading and writing of a - single character while in an atomic context. When kgdb makes an I/O - request to the debugger, kgdboc invokes a call back in the serial - core which in turn uses the call back in the uart driver. It is - certainly possible to extend kgdboc to work with non-uart based - consoles in the future. - - - When using kgdboc with a uart, the uart driver must implement two callbacks in the struct uart_ops. Example from drivers/8250.c: -#ifdef CONFIG_CONSOLE_POLL - .poll_get_char = serial8250_get_poll_char, - .poll_put_char = serial8250_put_poll_char, -#endif - - Any implementation specifics around creating a polling driver use the - #ifdef CONFIG_CONSOLE_POLL, as shown above. - Keep in mind that polling hooks have to be implemented in such a way - that they can be called from an atomic context and have to restore - the state of the uart chip on return such that the system can return - to normal when the debugger detaches. You need to be very careful - with any kind of lock you consider, because failing here is most - going to mean pressing the reset button. - - Kernel parameter: kgdbcon @@ -327,6 +297,8 @@ + KGDB Internals + Architecture Specifics Kgdb is organized into three basic components: @@ -365,18 +337,23 @@ kgdb I/O driver - Each kgdb I/O driver has to provide an configuration - initialization, and cleanup handler for when it - unloads/unconfigures. Any given kgdb I/O driver has to operate - very closely with the hardware and must do it in such a way that - does not enable interrupts or change other parts of the system - context without completely restoring them. Every kgdb I/O - driver must provide a read and write character interface. The - kgdb core will repeatedly "poll" a kgdb I/O driver for characters - when it needs input. The I/O driver is expected to return - immediately if there is no data available. Doing so allows for - the future possibility to touch watch dog hardware in such a way - as to have a target system not reset when these are enabled. + Each kgdb I/O driver has to provide an implemenation for the following: + + configuration via builtin or module + dynamic configuration and kgdb hook registration calls + read and write character interface + A cleanup handler for unconfiguring from the kgdb core + (optional) Early debug methodology + + Any given kgdb I/O driver has to operate very closely with the + hardware and must do it in such a way that does not enable + interrupts or change other parts of the system context without + completely restoring them. The kgdb core will repeatedly "poll" + a kgdb I/O driver for characters when it needs input. The I/O + driver is expected to return immediately if there is no data + available. Doing so allows for the future possibility to touch + watch dog hardware in such a way as to have a target system not + reset when these are enabled. @@ -419,6 +396,38 @@ does not need to provide a specific implementation. !Iinclude/linux/kgdb.h + + + kgdboc internals + + The kgdboc driver is actually a very thin driver that relies on the + underlying low level to the hardware driver having "polling hooks" + which the to which the tty driver is attached. In the initial + implementation of kgdboc it the serial_core was changed to expose a + low level uart hook for doing polled mode reading and writing of a + single character while in an atomic context. When kgdb makes an I/O + request to the debugger, kgdboc invokes a call back in the serial + core which in turn uses the call back in the uart driver. It is + certainly possible to extend kgdboc to work with non-uart based + consoles in the future. + + + When using kgdboc with a uart, the uart driver must implement two callbacks in the struct uart_ops. Example from drivers/8250.c: +#ifdef CONFIG_CONSOLE_POLL + .poll_get_char = serial8250_get_poll_char, + .poll_put_char = serial8250_put_poll_char, +#endif + + Any implementation specifics around creating a polling driver use the + #ifdef CONFIG_CONSOLE_POLL, as shown above. + Keep in mind that polling hooks have to be implemented in such a way + that they can be called from an atomic context and have to restore + the state of the uart chip on return such that the system can return + to normal when the debugger detaches. You need to be very careful + with any kind of lock you consider, because failing here is most + going to mean pressing the reset button. + + Credits @@ -427,8 +436,11 @@ Amit Kaleamitkale@linsyssoft.com Tom Rinitrini@kernel.crashing.org - Jason Wesseljason.wessel@windriver.com + In March 2008 this document was completely rewritten by: + + Jason Wesseljason.wessel@windriver.com + -- cgit v1.2.3 From a594eeb1a1d320981fccc29584b6f21fcebd765f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Fri, 18 Apr 2008 00:46:20 +0200 Subject: IDE: remove ide=reverse IDE core This option is obsolete and can be removed safely. It allows us to remove the pci_get_device_reverse() function from the PCI core. Signed-off-by: Greg Kroah-Hartman Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 2 -- Documentation/kernel-parameters.txt | 2 +- drivers/ide/Kconfig | 9 +-------- drivers/ide/ide-scan-pci.c | 9 ++------- drivers/ide/ide.c | 12 ------------ include/linux/ide.h | 1 - 6 files changed, 4 insertions(+), 31 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 818676aad45a..ce7c01af30f6 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -269,8 +269,6 @@ Summary of ide driver parameters for kernel command line ability to bit test for detection is currently unknown. - "ide=reverse" : formerly called to pci sub-system, but now local. - "ide=doubler" : probe/support IDE doublers on Amiga There may be more options than shown -- use the source, Luke! diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index dafd001bf833..228d85a3f319 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -763,7 +763,7 @@ and is between 256 and 4096 characters. It is defined in the file Format: [,[,[,]]] ide= [HW] (E)IDE subsystem - Format: ide=nodma or ide=doubler or ide=reverse + Format: ide=nodma or ide=doubler See Documentation/ide/ide.txt. ide?= [HW] (E)IDE subsystem diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index eed6d8e1b5c7..ac5875783430 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -416,12 +416,6 @@ config BLK_DEV_OFFBOARD This can improve the usability of some boot managers such as lilo when booting from a drive on an off-board controller. - If you say Y here, and you actually want to reverse the device scan - order as explained above, you also need to issue the kernel command - line option "ide=reverse". (Try "man bootparam" or see the - documentation of your boot loader (lilo or loadlin) about how to - pass options to the kernel at boot time.) - Note that, if you do this, the order of the hd* devices will be rearranged which may require modification of fstab and other files. @@ -615,8 +609,7 @@ config BLK_DEV_HPT366 reference to device 0x80. The other solution is to say Y to "Boot off-board chipsets first support" (CONFIG_BLK_DEV_OFFBOARD) unless your mother board has the chipset natively mounted. Regardless one - should use the fore mentioned option and call at LILO or include - "ide=reverse" in LILO's append-line. + should use the fore mentioned option and call at LILO. This driver requires dynamic tuning of the chipset during the ide-probe at boot. It is reported to support DVD II drives, by the diff --git a/drivers/ide/ide-scan-pci.c b/drivers/ide/ide-scan-pci.c index 93d2e41be853..98888da1b600 100644 --- a/drivers/ide/ide-scan-pci.c +++ b/drivers/ide/ide-scan-pci.c @@ -88,13 +88,8 @@ static int __init ide_scan_pcibus(void) struct list_head *l, *n; pre_init = 0; - if (!ide_scan_direction) - while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev))) - ide_scan_pcidev(dev); - else - while ((dev = pci_get_device_reverse(PCI_ANY_ID, PCI_ANY_ID, - dev))) - ide_scan_pcidev(dev); + while ((dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev))) + ide_scan_pcidev(dev); /* * Hand the drivers over to the PCI layer now we diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index fc69fe2e3ec0..5f545153391a 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -90,10 +90,6 @@ static int system_bus_speed; /* holds what we think is VESA/PCI bus speed */ DEFINE_MUTEX(ide_cfg_mtx); __cacheline_aligned_in_smp DEFINE_SPINLOCK(ide_lock); -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER -int ide_scan_direction; /* THIS was formerly 2.2.x pci=reverse */ -#endif - int noautodma = 0; #ifdef CONFIG_BLK_DEV_IDEACPI @@ -1217,14 +1213,6 @@ static int __init ide_setup(char *s) goto obsolete_option; } -#ifdef CONFIG_IDEPCI_PCIBUS_ORDER - if (!strcmp(s, "ide=reverse")) { - ide_scan_direction = 1; - printk(" : Enabled support for IDE inverse scan order.\n"); - goto obsolete_option; - } -#endif - #ifdef CONFIG_BLK_DEV_IDEACPI if (!strcmp(s, "ide=noacpi")) { //printk(" : Disable IDE ACPI support.\n"); diff --git a/include/linux/ide.h b/include/linux/ide.h index bc26b2f27359..43d2968a4e13 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -990,7 +990,6 @@ extern void do_ide_request(struct request_queue *); void ide_init_disk(struct gendisk *, ide_drive_t *); #ifdef CONFIG_IDEPCI_PCIBUS_ORDER -extern int ide_scan_direction; extern int __ide_pci_register_driver(struct pci_driver *driver, struct module *owner, const char *mod_name); #define ide_pci_register_driver(d) __ide_pci_register_driver(d, THIS_MODULE, KBUILD_MODNAME) #else -- cgit v1.2.3 From f74c91413ec6140ee0553180c5f56fdd27c22a2e Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 18 Apr 2008 00:46:23 +0200 Subject: ide: add warm-plug support for IDE devices (take 2) * Add 'struct class ide_port_class' ('ide_port' class) and a 'struct device *portdev' ('ide_port' class device) in ide_hwif_t. * Register 'ide_port' class in ide_init() and unregister it in cleanup_module(). * Create ->portdev in ide_register_port () and unregister it in ide_unregister(). * Add "delete_devices" class device attribute for unregistering IDE devices on a port and "scan" one for probing+registering IDE devices on a port. * Add ide_sysfs_register_port() helper for registering "delete_devices" and "scan" attributes with ->portdev. Call it in ide_device_add_all(). * Document IDE warm-plug support in Documentation/ide/warm-plug-howto.txt. v2: * Convert patch from using 'struct class_device' to use 'struct device'. (thanks to Kay Sievers for doing it) Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/warm-plug-howto.txt | 13 +++++++ drivers/ide/ide-probe.c | 71 ++++++++++++++++++++++++++++++++++- drivers/ide/ide.c | 24 ++++++++++++ include/linux/ide.h | 5 ++- 4 files changed, 110 insertions(+), 3 deletions(-) create mode 100644 Documentation/ide/warm-plug-howto.txt (limited to 'Documentation') diff --git a/Documentation/ide/warm-plug-howto.txt b/Documentation/ide/warm-plug-howto.txt new file mode 100644 index 000000000000..d5885468b072 --- /dev/null +++ b/Documentation/ide/warm-plug-howto.txt @@ -0,0 +1,13 @@ + +IDE warm-plug HOWTO +=================== + +To warm-plug devices on a port 'idex': + +# echo -n "1" > /sys/class/ide_port/idex/delete_devices + +unplug old device(s) and plug new device(s) + +# echo -n "1" > /sys/class/ide_port/idex/scan + +done diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 468c4ac4181d..510254ab3c9b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -623,7 +623,7 @@ static void hwif_release_dev (struct device *dev) complete(&hwif->gendev_rel_comp); } -static void ide_register_port(ide_hwif_t *hwif) +static int ide_register_port(ide_hwif_t *hwif) { int ret; @@ -639,9 +639,23 @@ static void ide_register_port(ide_hwif_t *hwif) } hwif->gendev.release = hwif_release_dev; ret = device_register(&hwif->gendev); - if (ret < 0) + if (ret < 0) { printk(KERN_WARNING "IDE: %s: device_register error: %d\n", __FUNCTION__, ret); + goto out; + } + + get_device(&hwif->gendev); + + hwif->portdev = device_create(ide_port_class, &hwif->gendev, + MKDEV(0, 0), hwif->name); + if (IS_ERR(hwif->portdev)) { + ret = PTR_ERR(hwif->portdev); + device_unregister(&hwif->gendev); + } + dev_set_drvdata(hwif->portdev, hwif); +out: + return ret; } /** @@ -1378,6 +1392,58 @@ static void ide_port_cable_detect(ide_hwif_t *hwif) } } +static ssize_t store_delete_devices(struct device *portdev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + if (strncmp(buf, "1", n)) + return -EINVAL; + + ide_port_unregister_devices(hwif); + + return n; +}; + +static DEVICE_ATTR(delete_devices, S_IWUSR, NULL, store_delete_devices); + +static ssize_t store_scan(struct device *portdev, + struct device_attribute *attr, + const char *buf, size_t n) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + if (strncmp(buf, "1", n)) + return -EINVAL; + + ide_port_unregister_devices(hwif); + ide_port_scan(hwif); + + return n; +}; + +static DEVICE_ATTR(scan, S_IWUSR, NULL, store_scan); + +static struct device_attribute *ide_port_attrs[] = { + &dev_attr_delete_devices, + &dev_attr_scan, + NULL +}; + +static int ide_sysfs_register_port(ide_hwif_t *hwif) +{ + int i, rc; + + for (i = 0; ide_port_attrs[i]; i++) { + rc = device_create_file(hwif->portdev, ide_port_attrs[i]); + if (rc) + break; + } + + return rc; +} + int ide_device_add_all(u8 *idx, const struct ide_port_info *d) { ide_hwif_t *hwif, *mate = NULL; @@ -1474,6 +1540,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) hwif = &ide_hwifs[idx[i]]; if (hwif->present) { + ide_sysfs_register_port(hwif); ide_proc_register_port(hwif); ide_proc_port_register_devices(hwif); } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index cb18ba8de22d..d791b1ffb586 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -78,6 +78,8 @@ /* default maximum number of failures */ #define IDE_DEFAULT_MAX_FAILURES 1 +struct class *ide_port_class; + static const u8 ide_hwif_to_major[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR, IDE4_MAJOR, IDE5_MAJOR, @@ -591,6 +593,7 @@ void ide_unregister(unsigned int index, int init_default, int restore) ide_remove_port_from_hwgroup(hwif); + device_unregister(hwif->portdev); device_unregister(&hwif->gendev); wait_for_completion(&hwif->gendev_rel_comp); @@ -1590,6 +1593,13 @@ struct bus_type ide_bus_type = { EXPORT_SYMBOL_GPL(ide_bus_type); +static void ide_port_class_release(struct device *portdev) +{ + ide_hwif_t *hwif = dev_get_drvdata(portdev); + + put_device(&hwif->gendev); +} + /* * This is gets invoked once during initialization, to set *everything* up */ @@ -1610,11 +1620,23 @@ static int __init ide_init(void) return ret; } + ide_port_class = class_create(THIS_MODULE, "ide_port"); + if (IS_ERR(ide_port_class)) { + ret = PTR_ERR(ide_port_class); + goto out_port_class; + } + ide_port_class->dev_release = ide_port_class_release; + init_ide_data(); proc_ide_create(); return 0; + +out_port_class: + bus_unregister(&ide_bus_type); + + return ret; } #ifdef MODULE @@ -1651,6 +1673,8 @@ void __exit cleanup_module (void) proc_ide_destroy(); + class_destroy(ide_port_class); + bus_unregister(&ide_bus_type); } diff --git a/include/linux/ide.h b/include/linux/ide.h index e43570a19200..9cebf3054080 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -579,7 +579,9 @@ typedef struct hwif_s { unsigned mmio : 1; /* host uses MMIO */ unsigned straight8 : 1; /* Alan's straight 8 check */ - struct device gendev; + struct device gendev; + struct device *portdev; + struct completion gendev_rel_comp; /* To deal with device release() */ void *hwif_data; /* extra hwif data */ @@ -1275,6 +1277,7 @@ extern struct mutex ide_cfg_mtx; #define local_irq_set(flags) do { local_save_flags((flags)); local_irq_enable_in_hardirq(); } while (0) extern struct bus_type ide_bus_type; +extern struct class *ide_port_class; /* check if CACHE FLUSH (EXT) command is supported (bits defined in ATA-6) */ #define ide_id_has_flush_cache(id) ((id)->cfs_enable_2 & 0x3000) -- cgit v1.2.3 From 80aa31cb460d12c1e02327b43eceb3eebc6e7090 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 18 Apr 2008 00:46:24 +0200 Subject: ide: remove CONFIG_BLK_DEV_HD_IDE config option (take 2) * Remove CONFIG_BLK_DEV_HD hack from init_hwif_default() ("hda=noprobe hdb=noprobe" kernel parameters should be used instead if somebody wishes to use the old "hd" driver). * Make CONFIG_BLK_DEV_HD_ONLY config option available also when IDE subsystem is used and update help entry. * Remove no longer needed CONFIG_BLK_DEV_HD_IDE config option. v2: * Update documentation to suggest "hda=noprobe hdb=noprobe" instead of obsoleted "ide0=noprobe". * Update Documentation/ide/ide.txt. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 7 ------- drivers/ide/Kconfig | 25 +++++-------------------- drivers/ide/ide.c | 4 ---- 3 files changed, 5 insertions(+), 31 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index ce7c01af30f6..ae4f4f43c25c 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -184,13 +184,6 @@ provided it is mounted with the default block size of 1024 (as above). Please pass on any feedback on any of this stuff to the maintainer, whose address can be found in linux/MAINTAINERS. -Note that if BOTH hd.c and ide.c are configured into the kernel, -hd.c will normally be allowed to control the primary IDE interface. -This is useful for older hardware that may be incompatible with ide.c, -and still allows newer hardware to run on the 2nd/3rd/4th IDE ports -under control of ide.c. To have ide.c also "take over" the primary -IDE port in this situation, use the "command line" parameter: ide0=0x1f0 - The IDE driver is modularized. The high level disk/CD-ROM/tape/floppy drivers can always be compiled as loadable modules, the chipset drivers can only be compiled into the kernel, and the core code (ide.c) can be diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index ac5875783430..4dc2761e9704 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -122,24 +122,6 @@ config BLK_DEV_IDE_SATA If unsure, say N. -config BLK_DEV_HD_IDE - bool "Use old disk-only driver on primary interface" - depends on (X86 || SH_MPC1211) - ---help--- - There are two drivers for MFM/RLL/IDE disks. Most people use just - the new enhanced driver by itself. This option however installs the - old hard disk driver to control the primary IDE/disk interface in - the system, leaving the new enhanced IDE driver to take care of only - the 2nd/3rd/4th IDE interfaces. Doing this will prevent you from - having an IDE/ATAPI CD-ROM or tape drive connected to the primary - IDE interface. Choosing this option may be useful for older systems - which have MFM/RLL/ESDI controller+drives at the primary port - address (0x1f0), along with IDE drives at the secondary/3rd/4th port - addresses. - - Normally, just say N here; you will then use the new driver for all - 4 interfaces. - config BLK_DEV_IDEDISK tristate "Include IDE/ATA-2 DISK support" ---help--- @@ -1114,7 +1096,6 @@ endif config BLK_DEV_HD_ONLY bool "Old hard disk (MFM/RLL/IDE) driver" - depends on BLK_DEV_IDE=n help There are two drivers for MFM/RLL/IDE hard disks. Most people use the newer enhanced driver, but this old one is still around for two @@ -1126,12 +1107,16 @@ config BLK_DEV_HD_ONLY for systems with only older MFM/RLL/ESDI drives. Choosing the old driver can save 13 KB or so of kernel memory. + If you want to use this driver together with the new one you have + to use "hda=noprobe hdb=noprobe" kernel parameters to prevent the new + driver from probing the primary interface. + If you are unsure, then just choose the Enhanced IDE/MFM/RLL driver instead of this one. For more detailed information, read the Disk-HOWTO, available from . config BLK_DEV_HD - def_bool BLK_DEV_HD_IDE || BLK_DEV_HD_ONLY + def_bool BLK_DEV_HD_ONLY endif # IDE diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index d791b1ffb586..96126b3b12e9 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -177,10 +177,6 @@ static void init_hwif_default(ide_hwif_t *hwif, unsigned int index) memcpy(hwif->io_ports, hw.io_ports, sizeof(hw.io_ports)); hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET]; -#ifdef CONFIG_BLK_DEV_HD - if (hwif->io_ports[IDE_DATA_OFFSET] == HD_DATA) - hwif->noprobe = 1; /* may be overridden by ide_setup() */ -#endif } /* -- cgit v1.2.3 From 9a0e77f28b50128df0c9e26ae489e44e29a7270a Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 18 Apr 2008 00:46:24 +0200 Subject: ide: remove obsoleted "idex=base[,ctl[,irq]]" kernel parameters (take 2) * Remove obsoleted "idex=base[,ctl[,irq]]" kernel parameters and update Documentation/ide/ide.txt. * Remove no longer needed ide_forced chipset type. v2: * is_chipset_set[] -> is_chipset_set in ide.c. * Documentation/ide/ide.txt fix. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 33 +-------------------------------- drivers/ide/ide-generic.c | 3 +-- drivers/ide/ide-probe.c | 3 +-- drivers/ide/ide-proc.c | 3 --- drivers/ide/ide.c | 41 ++++++++++++----------------------------- drivers/ide/pci/cmd640.c | 2 +- drivers/ide/setup-pci.c | 11 ----------- include/linux/ide.h | 2 +- 8 files changed, 17 insertions(+), 81 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index ae4f4f43c25c..18c02df2f78f 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -71,29 +71,6 @@ This driver automatically probes for most IDE interfaces (including all PCI ones), for the drives/geometries attached to those interfaces, and for the IRQ lines being used by the interfaces (normally 14, 15 for ide0/ide1). -For special cases, interfaces may be specified using kernel "command line" -options. For example, - - ide3=0x168,0x36e,10 /* ioports 0x168-0x16f,0x36e, irq 10 */ - -Normally the irq number need not be specified, as ide.c will probe for it: - - ide3=0x168,0x36e /* ioports 0x168-0x16f,0x36e */ - -The standard port, and irq values are these: - - ide0=0x1f0,0x3f6,14 - ide1=0x170,0x376,15 - ide2=0x1e8,0x3ee,11 - ide3=0x168,0x36e,10 - -Note that the first parameter reserves 8 contiguous ioports, whereas the -second value denotes a single ioport. If in doubt, do a 'cat /proc/ioports'. - -In all probability the device uses these ports and IRQs if it is attached -to the appropriate ide channel. Pass the parameter for the correct ide -channel to the kernel, as explained above. - Any number of interfaces may share a single IRQ if necessary, at a slight performance penalty, whether on separate cards or a single VLB card. The IDE driver automatically detects and handles this. However, this may @@ -199,7 +176,7 @@ When ide.c is used as a module, you can pass command line parameters to the driver using the "options=" keyword to insmod, while replacing any ',' with ';'. For example: - insmod ide.o options="ide0=serialize ide1=serialize ide2=0x1e8;0x3ee;11" + insmod ide.o options="hda=nodma hdb=nodma" ================================================================================ @@ -240,14 +217,6 @@ Summary of ide driver parameters for kernel command line As for VLB, it is safest to not specify it. Bigger values are safer than smaller ones. - "idex=base" : probe for an interface at the addr specified, - where "base" is usually 0x1f0 or 0x170 - and "ctl" is assumed to be "base"+0x206 - - "idex=base,ctl" : specify both base and ctl - - "idex=base,ctl,irq" : specify base, ctl, and irq number - "idex=serialize" : do not overlap operations on idex. Please note that you will have to specify this option for both the respective primary and secondary channel diff --git a/drivers/ide/ide-generic.c b/drivers/ide/ide-generic.c index 387574fe4b2b..bae41459192d 100644 --- a/drivers/ide/ide-generic.c +++ b/drivers/ide/ide-generic.c @@ -93,8 +93,7 @@ static int __init ide_generic_init(void) ide_hwif_t *hwif = &ide_hwifs[i]; if (hwif->io_ports[IDE_DATA_OFFSET] && - (hwif->chipset == ide_unknown || - hwif->chipset == ide_forced)) + hwif->chipset == ide_unknown) idx[i] = i; else idx[i] = 0xff; diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 8ef5194f6d47..33cb5e5a249b 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1519,8 +1519,7 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) hwif = &ide_hwifs[idx[i]]; if (hwif->present) { - if (hwif->chipset == ide_unknown || - hwif->chipset == ide_forced) + if (hwif->chipset == ide_unknown) hwif->chipset = ide_generic; hwif_register_devices(hwif); } diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c index 77025d1057b5..edd7f186dc4d 100644 --- a/drivers/ide/ide-proc.c +++ b/drivers/ide/ide-proc.c @@ -46,9 +46,6 @@ static int proc_ide_read_imodel int len; const char *name; - /* - * Neither ide_unknown nor ide_forced should be set at this point. - */ switch (hwif->chipset) { case ide_generic: name = "generic"; break; case ide_pci: name = "pci"; break; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 96126b3b12e9..7e789c97a8b8 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1170,7 +1170,7 @@ extern int probe_ht6560b; extern int probe_qd65xx; extern int cmd640_vlb; -static int __initdata is_chipset_set[MAX_HWIFS]; +static int __initdata is_chipset_set; /* * ide_setup() gets called VERY EARLY during initialization, @@ -1328,8 +1328,6 @@ static int __init ide_setup(char *s) "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", NULL }; - hw_regs_t hwregs; - hw = s[3] - '0'; hwif = &ide_hwifs[hw]; i = match_parm(&s[4], ide_words, vals, 3); @@ -1338,19 +1336,14 @@ static int __init ide_setup(char *s) * Cryptic check to ensure chipset not already set for hwif. * Note: we can't depend on hwif->chipset here. */ - if ((i >= -18 && i <= -11) || (i > 0 && i <= 3)) { + if (i >= -18 && i <= -11) { /* chipset already specified */ - if (is_chipset_set[hw]) + if (is_chipset_set) goto bad_option; - if (i > -18 && i <= -11) { - /* these drivers are for "ide0=" only */ - if (hw != 0) - goto bad_hwif; - /* chipset already specified for 2nd port */ - if (is_chipset_set[hw+1]) - goto bad_option; - } - is_chipset_set[hw] = 1; + /* these drivers are for "ide0=" only */ + if (hw != 0) + goto bad_hwif; + is_chipset_set = 1; printk("\n"); } @@ -1430,21 +1423,11 @@ static int __init ide_setup(char *s) case -1: /* "noprobe" */ hwif->noprobe = 1; goto obsolete_option; - - case 1: /* base */ - vals[1] = vals[0] + 0x206; /* default ctl */ - case 2: /* base,ctl */ - vals[2] = 0; /* default irq = probe for it */ - case 3: /* base,ctl,irq */ - memset(&hwregs, 0, sizeof(hwregs)); - ide_init_hwif_ports(&hwregs, vals[0], vals[1], &hwif->irq); - memcpy(hwif->io_ports, hwregs.io_ports, sizeof(hwif->io_ports)); - hwif->irq = vals[2]; - hwif->noprobe = 0; - hwif->chipset = ide_forced; - goto obsolete_option; - - case 0: goto bad_option; + case 0: + case 1: + case 2: + case 3: + goto bad_option; default: printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); return 1; diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 29fbc5ead03b..58a95f62e383 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -415,7 +415,7 @@ static void __init setup_device_ptrs (void) cmd_hwif1 = &ide_hwifs[1]; /* default, if not found below */ for (i = 0; i < MAX_HWIFS; i++) { ide_hwif_t *hwif = &ide_hwifs[i]; - if (hwif->chipset == ide_unknown || hwif->chipset == ide_forced) { + if (hwif->chipset == ide_unknown) { if (hwif->io_ports[IDE_DATA_OFFSET] == 0x1f0) cmd_hwif0 = hwif; else if (hwif->io_ports[IDE_DATA_OFFSET] == 0x170) diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 634e3f6a9608..ea66c996e4ec 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -40,17 +40,6 @@ static ide_hwif_t *ide_match_hwif(unsigned long io_base, u8 bootable, const char int h; ide_hwif_t *hwif; - /* - * Look for a hwif with matching io_base specified using - * parameters to ide_setup(). - */ - for (h = 0; h < MAX_HWIFS; ++h) { - hwif = &ide_hwifs[h]; - if (hwif->io_ports[IDE_DATA_OFFSET] == io_base) { - if (hwif->chipset == ide_forced) - return hwif; /* a perfect match */ - } - } /* * Look for a hwif with matching io_base default value. * If chipset is "ide_unknown", then claim that hwif slot. diff --git a/include/linux/ide.h b/include/linux/ide.h index 9cebf3054080..67f83c60845f 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -169,7 +169,7 @@ enum { ide_unknown, ide_generic, ide_pci, ide_rz1000, ide_trm290, ide_cmd646, ide_cy82c693, ide_4drives, ide_pmac, ide_etrax100, ide_acorn, - ide_au1xxx, ide_palm3710, ide_forced + ide_au1xxx, ide_palm3710 }; typedef u8 hwif_chipset_t; -- cgit v1.2.3 From ffd4f6f0eed0423652826f3775077d11918b4180 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 18 Apr 2008 00:46:34 +0200 Subject: ide: add ide-4drives host driver (take 3) CONFIG_BLK_DEV_4DRIVES deserves its own host driver: * Add drivers/ide/legacy/ide-4drives.c and move "4drives" support there. * Add ide-4drives.o in the link order after all other legacy host drivers enabled by "ide0=" options (they all are mutually exclusive). * Make ide-4drives host driver probe itself for IDE devices instead of indirectly depending on ide_generic host driver. * Add "probe" module parameter to ide-4drives and update documentation. v2: * s/paramater/parameter/ in ide.txt. (Noticed by Randy Dunlap) v3: * s/ide_4drives.probe/ide-4drives.probe/ in help entry. (Noticed by Sergei Shtylyov) Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 5 +++-- drivers/ide/Kconfig | 4 ++-- drivers/ide/ide.c | 15 +++---------- drivers/ide/legacy/Makefile | 1 + drivers/ide/legacy/ide-4drives.c | 46 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 55 insertions(+), 16 deletions(-) create mode 100644 drivers/ide/legacy/ide-4drives.c (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 18c02df2f78f..486c699f4aea 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -222,8 +222,6 @@ Summary of ide driver parameters for kernel command line both the respective primary and secondary channel to take effect. - "idex=four" : four drives on idex and ide(x^1) share same ports - "idex=reset" : reset interface after probe "idex=ata66" : informs the interface that it has an 80c cable @@ -250,6 +248,9 @@ Also for legacy CMD640 host driver (cmd640) you need to use "probe_vlb" kernel paremeter to enable probing for VLB version of the chipset (PCI ones are detected automatically). +You also need to use "probe" kernel parameter for ide-4drives driver +(support for IDE generic chipset with four drives on one port). + ================================================================================ Some Terminology diff --git a/drivers/ide/Kconfig b/drivers/ide/Kconfig index 29dd99caaf50..ec6b4a80e333 100644 --- a/drivers/ide/Kconfig +++ b/drivers/ide/Kconfig @@ -1035,8 +1035,8 @@ config BLK_DEV_4DRIVES Certain older chipsets, including the Tekram 690CD, use a single set of I/O ports at 0x1f0 to control up to four drives, instead of the customary two drives per port. Support for this can be enabled at - runtime using the "ide0=four" kernel boot parameter if you say Y - here. + runtime using the "ide-4drives.probe" kernel boot parameter if you + say Y here. config BLK_DEV_ALI14XX tristate "ALI M14xx support" diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index adecf45a0849..690b5ff4d88f 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -976,6 +976,7 @@ extern int probe_dtc2278; extern int probe_ht6560b; extern int probe_qd65xx; extern int cmd640_vlb; +extern int probe_4drives; static int __initdata is_chipset_set; @@ -1187,19 +1188,9 @@ static int __init ide_setup(char *s) #endif #ifdef CONFIG_BLK_DEV_4DRIVES case -11: /* "four" drives on one set of ports */ - { - ide_hwif_t *mate = &ide_hwifs[hw^1]; - mate->drives[0].select.all ^= 0x20; - mate->drives[1].select.all ^= 0x20; - hwif->chipset = mate->chipset = ide_4drives; - mate->irq = hwif->irq; - memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports)); - hwif->mate = mate; - mate->mate = hwif; - hwif->serialized = mate->serialized = 1; + probe_4drives = 1; goto obsolete_option; - } -#endif /* CONFIG_BLK_DEV_4DRIVES */ +#endif case -10: /* minus10 */ case -9: /* minus9 */ case -8: /* minus8 */ diff --git a/drivers/ide/legacy/Makefile b/drivers/ide/legacy/Makefile index 7043ec7d1e05..6939329f89e8 100644 --- a/drivers/ide/legacy/Makefile +++ b/drivers/ide/legacy/Makefile @@ -6,6 +6,7 @@ obj-$(CONFIG_BLK_DEV_UMC8672) += umc8672.o obj-$(CONFIG_BLK_DEV_DTC2278) += dtc2278.o obj-$(CONFIG_BLK_DEV_HT6560B) += ht6560b.o obj-$(CONFIG_BLK_DEV_QD65XX) += qd65xx.o +obj-$(CONFIG_BLK_DEV_4DRIVES) += ide-4drives.o obj-$(CONFIG_BLK_DEV_GAYLE) += gayle.o obj-$(CONFIG_BLK_DEV_FALCON_IDE) += falconide.o diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c new file mode 100644 index 000000000000..5aa7e93cfd31 --- /dev/null +++ b/drivers/ide/legacy/ide-4drives.c @@ -0,0 +1,46 @@ + +#include +#include +#include +#include + +int probe_4drives = 0; + +module_param_named(probe, probe_4drives, bool, 0); +MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port"); + +static int __init ide_4drives_init(void) +{ + ide_hwif_t *hwif, *mate; + u8 idx[4] = { 0, 1, 0xff, 0xff }; + + if (probe_4drives == 0) + return -ENODEV; + + hwif = &ide_hwifs[0]; + mate = &ide_hwifs[1]; + + memcpy(mate->io_ports, hwif->io_ports, sizeof(hwif->io_ports)); + + mate->irq = hwif->irq; + + mate->chipset = hwif->chipset = ide_4drives; + + mate->drives[0].select.all ^= 0x20; + mate->drives[1].select.all ^= 0x20; + + hwif->mate = mate; + mate->mate = hwif; + + hwif->serialized = mate->serialized = 1; + + ide_device_add(idx, NULL); + + return 0; +} + +module_init(ide_4drives_init); + +MODULE_AUTHOR("Bartlomiej Zolnierkiewicz"); +MODULE_DESCRIPTION("generic IDE chipset with 4 drives/port support"); +MODULE_LICENSE("GPL"); -- cgit v1.2.3 From f01674e459923c6df540e6c983d37e5fc94d43b8 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Fri, 18 Apr 2008 00:46:35 +0200 Subject: ide: remove obsoleted "idex=noprobe" kernel parameter (take 2) * Remove obsoleted "idex=noprobe" kernel parameter. * Remove no longer needed hwif->noprobe quirk from ide_hwif_configure() and hwif->noprobe checking from cmd640.c. v2: * "ide?=noprobe" -> "ide?=ata66" in Documentation/kernel-parameters.txt. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/kernel-parameters.txt | 2 +- drivers/ide/ide.c | 6 ++---- drivers/ide/pci/cmd640.c | 3 +-- drivers/ide/setup-pci.c | 7 ------- 4 files changed, 4 insertions(+), 14 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 228d85a3f319..239e78a1fcd0 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -767,7 +767,7 @@ and is between 256 and 4096 characters. It is defined in the file See Documentation/ide/ide.txt. ide?= [HW] (E)IDE subsystem - Format: ide?=noprobe or chipset specific parameters. + Format: ide?=ata66 or chipset specific parameters. See Documentation/ide/ide.txt. idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 690b5ff4d88f..aa809aded87f 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1131,7 +1131,7 @@ static int __init ide_setup(char *s) * (-8, -9, -10) are reserved to ease the hardcoding. */ static const char *ide_words[] = { - "noprobe", "serialize", "minus3", "minus4", + "minus1", "serialize", "minus3", "minus4", "reset", "minus6", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", NULL }; @@ -1218,9 +1218,7 @@ static int __init ide_setup(char *s) hwif->serialized = hwif->mate->serialized = 1; goto obsolete_option; - case -1: /* "noprobe" */ - hwif->noprobe = 1; - goto obsolete_option; + case -1: case 0: case 1: case 2: diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index dbf0fa733b76..a1cfe033a55f 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -789,8 +789,7 @@ static int __init cmd640x_init(void) /* * Try to enable the secondary interface, if not already enabled */ - if (cmd_hwif1->noprobe || - (cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe)) { + if (cmd_hwif1->drives[0].noprobe && cmd_hwif1->drives[1].noprobe) { port2 = "not probed"; } else { b = get_cmd640_reg(CNTRL); diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index ee4a34b49062..f7ede0e42881 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c @@ -345,7 +345,6 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, unsigned long ctl = 0, base = 0; ide_hwif_t *hwif; u8 bootable = (d->host_flags & IDE_HFLAG_BOOTABLE) ? 1 : 0; - u8 oldnoprobe = 0; struct hw_regs_s hw; if ((d->host_flags & IDE_HFLAG_ISA_PORTS) == 0) { @@ -376,14 +375,8 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, hw.chipset = d->chipset ? d->chipset : ide_pci; ide_std_init_ports(&hw, base, ctl | 2); - if (hwif->io_ports[IDE_DATA_OFFSET] == base && - hwif->io_ports[IDE_CONTROL_OFFSET] == (ctl | 2)) - oldnoprobe = hwif->noprobe; - ide_init_port_hw(hwif, &hw); - hwif->noprobe = oldnoprobe; - hwif->dev = &dev->dev; hwif->cds = d; -- cgit v1.2.3 From 033bfb1a65242e0d60e6fc991cd9b3553053d334 Mon Sep 17 00:00:00 2001 From: David Chinner Date: Fri, 11 Apr 2008 17:05:49 +1000 Subject: [XFS] Update XFS Documentation for ikeep and ihashsize Update xfs docs for: * In memory inode hashes has been removed. * noikeep is now the default. SGI-PV: 969561 SGI-Modid: 2.6.x-xfs-melb:linux:29481b Signed-off-by: David Chinner Signed-off-by: Christoph Hellwig Signed-off-by: Tim Shimmin --- Documentation/filesystems/xfs.txt | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt index 74aeb142ae5f..10ba81f4be0d 100644 --- a/Documentation/filesystems/xfs.txt +++ b/Documentation/filesystems/xfs.txt @@ -52,16 +52,14 @@ When mounting an XFS filesystem, the following options are accepted. and also gets the setgid bit set if it is a directory itself. ihashsize=value - Sets the number of hash buckets available for hashing the - in-memory inodes of the specified mount point. If a value - of zero is used, the value selected by the default algorithm - will be displayed in /proc/mounts. + In memory inode hashes have been removed, so this option has + no function as of August 2007. Option is deprecated. ikeep/noikeep - When inode clusters are emptied of inodes, keep them around - on the disk (ikeep) - this is the traditional XFS behaviour - and is still the default for now. Using the noikeep option, - inode clusters are returned to the free space pool. + When ikeep is specified, XFS does not delete empty inode clusters + and keeps them around on disk. ikeep is the traditional XFS + behaviour. When noikeep is specified, empty inode clusters + are returned to the free space pool. The default is noikeep. inode64 Indicates that XFS is allowed to create inodes at any location -- cgit v1.2.3 From f6e9f28865552bd9d79a9df93cf120436b073223 Mon Sep 17 00:00:00 2001 From: Josef Sipek Date: Fri, 11 Apr 2008 17:11:02 +1000 Subject: [XFS] Update XFS documentation for noikeep/ikeep. Mention how DMAPI affects default for noikeep. Slightly modified since Josef's patch was based on an old xfs.txt prior to Dave's (dgc) checkin which missed going to oss. Signed-off-by: Josef Sipek Signed-off-by: Tim Shimmin --- Documentation/filesystems/xfs.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/xfs.txt b/Documentation/filesystems/xfs.txt index 10ba81f4be0d..0a1668ba2600 100644 --- a/Documentation/filesystems/xfs.txt +++ b/Documentation/filesystems/xfs.txt @@ -59,7 +59,8 @@ When mounting an XFS filesystem, the following options are accepted. When ikeep is specified, XFS does not delete empty inode clusters and keeps them around on disk. ikeep is the traditional XFS behaviour. When noikeep is specified, empty inode clusters - are returned to the free space pool. The default is noikeep. + are returned to the free space pool. The default is noikeep for + non-DMAPI mounts, while ikeep is the default when DMAPI is in use. inode64 Indicates that XFS is allowed to create inodes at any location -- cgit v1.2.3 From 080de8c2c57e3199eee837fe8b6d35a43679f8c1 Mon Sep 17 00:00:00 2001 From: Stefan Richter Date: Thu, 28 Feb 2008 20:54:43 +0100 Subject: firewire: fw-ohci: add option for remote debugging This way firewire-ohci can be used for remote debugging like ohci1394. Version with amendment from Fri, 11 Apr 2008 00:08:08 +0200. Signed-off-by: Stefan Richter Acked-by: Bernhard Kaindl --- Documentation/debugging-via-ohci1394.txt | 16 ++++++++++------ drivers/firewire/fw-ohci.c | 9 +++++++++ lib/Kconfig.debug | 13 ++++++++++++- 3 files changed, 31 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/debugging-via-ohci1394.txt b/Documentation/debugging-via-ohci1394.txt index c360d4e91b48..59a91e5c6909 100644 --- a/Documentation/debugging-via-ohci1394.txt +++ b/Documentation/debugging-via-ohci1394.txt @@ -41,15 +41,19 @@ to a working state and enables physical DMA by default for all remote nodes. This can be turned off by ohci1394's module parameter phys_dma=0. The alternative firewire-ohci driver in drivers/firewire uses filtered physical -DMA, hence is not yet suitable for remote debugging. +DMA by default, which is more secure but not suitable for remote debugging. +Compile the driver with CONFIG_FIREWIRE_OHCI_REMOTE_DMA (Kernel hacking menu: +Remote debugging over FireWire with firewire-ohci) to get unfiltered physical +DMA. -Because ohci1394 depends on the PCI enumeration to be completed, an -initialization routine which runs pretty early (long before console_init() -which makes the printk buffer appear on the console can be called) was written. +Because ohci1394 and firewire-ohci depend on the PCI enumeration to be +completed, an initialization routine which runs pretty early has been +implemented for x86. This routine runs long before console_init() can be +called, i.e. before the printk buffer appears on the console. To activate it, enable CONFIG_PROVIDE_OHCI1394_DMA_INIT (Kernel hacking menu: -Provide code for enabling DMA over FireWire early on boot) and pass the -parameter "ohci1394_dma=early" to the recompiled kernel on boot. +Remote debugging over FireWire early on boot) and pass the parameter +"ohci1394_dma=early" to the recompiled kernel on boot. Tools ----- diff --git a/drivers/firewire/fw-ohci.c b/drivers/firewire/fw-ohci.c index 07d6053ff57e..5da7c6715e1e 100644 --- a/drivers/firewire/fw-ohci.c +++ b/drivers/firewire/fw-ohci.c @@ -1097,6 +1097,11 @@ static void bus_reset_tasklet(unsigned long data) reg_write(ohci, OHCI1394_ConfigROMhdr, ohci->next_header); } +#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA + reg_write(ohci, OHCI1394_PhyReqFilterHiSet, ~0); + reg_write(ohci, OHCI1394_PhyReqFilterLoSet, ~0); +#endif + spin_unlock_irqrestore(&ohci->lock, flags); if (free_rom) @@ -1435,6 +1440,9 @@ static int ohci_cancel_packet(struct fw_card *card, struct fw_packet *packet) static int ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) { +#ifdef CONFIG_FIREWIRE_OHCI_REMOTE_DMA + return 0; +#else struct fw_ohci *ohci = fw_ohci(card); unsigned long flags; int n, retval = 0; @@ -1466,6 +1474,7 @@ ohci_enable_phys_dma(struct fw_card *card, int node_id, int generation) out: spin_unlock_irqrestore(&ohci->lock, flags); return retval; +#endif /* CONFIG_FIREWIRE_OHCI_REMOTE_DMA */ } static u64 diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 0796c1a090c0..78955eb6bd94 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -593,7 +593,7 @@ config LATENCYTOP to find out which userspace is blocking on what kernel operations. config PROVIDE_OHCI1394_DMA_INIT - bool "Provide code for enabling DMA over FireWire early on boot" + bool "Remote debugging over FireWire early on boot" depends on PCI && X86 help If you want to debug problems which hang or crash the kernel early @@ -621,4 +621,15 @@ config PROVIDE_OHCI1394_DMA_INIT See Documentation/debugging-via-ohci1394.txt for more information. +config FIREWIRE_OHCI_REMOTE_DMA + bool "Remote debugging over FireWire with firewire-ohci" + depends on FIREWIRE_OHCI + help + This option lets you use the FireWire bus for remote debugging + with help of the firewire-ohci driver. It enables unfiltered + remote DMA in firewire-ohci. + See Documentation/debugging-via-ohci1394.txt for more information. + + If unsure, say N. + source "samples/Kconfig" -- cgit v1.2.3 From 53f67e33865927049b20839ce15ce0fb5b7ebe2d Mon Sep 17 00:00:00 2001 From: Joel Becker Date: Mon, 31 Mar 2008 16:22:55 -0700 Subject: ocfs2: Document /sys/fs/ocfs2 Add ABI documentation for these files: /sys/fs/ocfs2/max_locking_protocol /sys/fs/ocfs2/loaded_cluster_plugins /sys/fs/ocfs2/active_cluster_plugin /sys/fs/ocfs2/cluster_stack Signed-off-by: Joel Becker Signed-off-by: Mark Fasheh --- Documentation/ABI/testing/sysfs-ocfs2 | 89 +++++++++++++++++++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-ocfs2 (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-ocfs2 b/Documentation/ABI/testing/sysfs-ocfs2 new file mode 100644 index 000000000000..b7cc516a8a8a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-ocfs2 @@ -0,0 +1,89 @@ +What: /sys/fs/ocfs2/ +Date: April 2008 +Contact: ocfs2-devel@oss.oracle.com +Description: + The /sys/fs/ocfs2 directory contains knobs used by the + ocfs2-tools to interact with the filesystem. + +What: /sys/fs/ocfs2/max_locking_protocol +Date: April 2008 +Contact: ocfs2-devel@oss.oracle.com +Description: + The /sys/fs/ocfs2/max_locking_protocol file displays version + of ocfs2 locking supported by the filesystem. This version + covers how ocfs2 uses distributed locking between cluster + nodes. + + The protocol version has a major and minor number. Two + cluster nodes can interoperate if they have an identical + major number and an overlapping minor number - thus, + a node with version 1.10 can interoperate with a node + sporting version 1.8, as long as both use the 1.8 protocol. + + Reading from this file returns a single line, the major + number and minor number joined by a period, eg "1.10". + + This file is read-only. The value is compiled into the + driver. + +What: /sys/fs/ocfs2/loaded_cluster_plugins +Date: April 2008 +Contact: ocfs2-devel@oss.oracle.com +Description: + The /sys/fs/ocfs2/loaded_cluster_plugins file describes + the available plugins to support ocfs2 cluster operation. + A cluster plugin is required to use ocfs2 in a cluster. + There are currently two available plugins: + + * 'o2cb' - The classic o2cb cluster stack that ocfs2 has + used since its inception. + * 'user' - A plugin supporting userspace cluster software + in conjunction with fs/dlm. + + Reading from this file returns the names of all loaded + plugins, one per line. + + This file is read-only. Its contents may change as + plugins are loaded or removed. + +What: /sys/fs/ocfs2/active_cluster_plugin +Date: April 2008 +Contact: ocfs2-devel@oss.oracle.com +Description: + The /sys/fs/ocfs2/active_cluster_plugin displays which + cluster plugin is currently in use by the filesystem. + The active plugin will appear in the loaded_cluster_plugins + file as well. Only one plugin can be used at a time. + + Reading from this file returns the name of the active plugin + on a single line. + + This file is read-only. Which plugin is active depends on + the cluster stack in use. The contents may change + when all filesystems are unmounted and the cluster stack + is changed. + +What: /sys/fs/ocfs2/cluster_stack +Date: April 2008 +Contact: ocfs2-devel@oss.oracle.com +Description: + The /sys/fs/ocfs2/cluster_stack file contains the name + of current ocfs2 cluster stack. This value is set by + userspace tools when bringing the cluster stack online. + + Cluster stack names are 4 characters in length. + + When the 'o2cb' cluster stack is used, the 'o2cb' cluster + plugin is active. All other cluster stacks use the 'user' + cluster plugin. + + Reading from this file returns the name of the current + cluster stack on a single line. + + Writing a new stack name to this file changes the current + cluster stack unless there are mounted ocfs2 filesystems. + If there are mounted filesystems, attempts to change the + stack return an error. + +Users: + ocfs2-tools -- cgit v1.2.3 From 52f7c21b613f80cb425d115c9e5b4ed958a133c0 Mon Sep 17 00:00:00 2001 From: Mark Fasheh Date: Tue, 29 Jan 2008 17:08:26 -0800 Subject: ocfs2: Move /sys/o2cb to /sys/fs/o2cb /sys/fs is where we really want file system specific sysfs objects. Ocfs2-tools has been updated to look in /sys/fs/o2cb. We can maintain backwards compatibility with old ocfs2-tools by using a sysfs symlink. After some time (2 years), the symlink can be safely removed. This patch also adds documentation to make it easier for people to figure out what /sys/fs/o2cb is used for. Signed-off-by: Mark Fasheh --- Documentation/ABI/obsolete/o2cb | 11 +++++++++++ Documentation/ABI/stable/o2cb | 10 ++++++++++ Documentation/feature-removal-schedule.txt | 10 ++++++++++ fs/ocfs2/cluster/sys.c | 9 +++++++++ 4 files changed, 40 insertions(+) create mode 100644 Documentation/ABI/obsolete/o2cb create mode 100644 Documentation/ABI/stable/o2cb (limited to 'Documentation') diff --git a/Documentation/ABI/obsolete/o2cb b/Documentation/ABI/obsolete/o2cb new file mode 100644 index 000000000000..9c49d8e6c0cc --- /dev/null +++ b/Documentation/ABI/obsolete/o2cb @@ -0,0 +1,11 @@ +What: /sys/o2cb symlink +Date: Dec 2005 +KernelVersion: 2.6.16 +Contact: ocfs2-devel@oss.oracle.com +Description: This is a symlink: /sys/o2cb to /sys/fs/o2cb. The symlink will + be removed when new versions of ocfs2-tools which know to look + in /sys/fs/o2cb are sufficiently prevalent. Don't code new + software to look here, it should try /sys/fs/o2cb instead. + See Documentation/ABI/stable/o2cb for more information on usage. +Users: ocfs2-tools. It's sufficient to mail proposed changes to + ocfs2-devel@oss.oracle.com. diff --git a/Documentation/ABI/stable/o2cb b/Documentation/ABI/stable/o2cb new file mode 100644 index 000000000000..5eb1545e0b8d --- /dev/null +++ b/Documentation/ABI/stable/o2cb @@ -0,0 +1,10 @@ +What: /sys/fs/o2cb/ (was /sys/o2cb) +Date: Dec 2005 +KernelVersion: 2.6.16 +Contact: ocfs2-devel@oss.oracle.com +Description: Ocfs2-tools looks at 'interface-revision' for versioning + information. Each logmask/ file controls a set of debug prints + and can be written into with the strings "allow", "deny", or + "off". Reading the file returns the current state. +Users: ocfs2-tools. It's sufficient to mail proposed changes to + ocfs2-devel@oss.oracle.com. diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index bf0e3df8e7a1..4101f1f2d1eb 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -318,3 +318,13 @@ Why: Not used in-tree. The current out-of-tree users used it to code / infrastructure should be in the kernel and not in some out-of-tree driver. Who: Thomas Gleixner + +--------------------------- + +What: /sys/o2cb symlink +When: January 2010 +Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb + exists as a symlink for backwards compatibility for old versions of + ocfs2-tools. 2 years should be sufficient time to phase in new versions + which know to look in /sys/fs/o2cb. +Who: ocfs2-devel@oss.oracle.com diff --git a/fs/ocfs2/cluster/sys.c b/fs/ocfs2/cluster/sys.c index 0c095ce7723d..98429fd68499 100644 --- a/fs/ocfs2/cluster/sys.c +++ b/fs/ocfs2/cluster/sys.c @@ -57,6 +57,7 @@ static struct kset *o2cb_kset; void o2cb_sys_shutdown(void) { mlog_sys_shutdown(); + sysfs_remove_link(NULL, "o2cb"); kset_unregister(o2cb_kset); } @@ -68,6 +69,14 @@ int o2cb_sys_init(void) if (!o2cb_kset) return -ENOMEM; + /* + * Create this symlink for backwards compatibility with old + * versions of ocfs2-tools which look for things in /sys/o2cb. + */ + ret = sysfs_create_link(NULL, &o2cb_kset->kobj, "o2cb"); + if (ret) + goto error; + ret = sysfs_create_group(&o2cb_kset->kobj, &o2cb_attr_group); if (ret) goto error; -- cgit v1.2.3 From 076c54c5bcaed2081c0cba94a6f77c4d470236ad Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Thu, 6 Mar 2008 18:09:10 +0200 Subject: Security: Introduce security= boot parameter Add the security= boot parameter. This is done to avoid LSM registration clashes in case of more than one bult-in module. User can choose a security module to enable at boot. If no security= boot parameter is specified, only the first LSM asking for registration will be loaded. An invalid security module name will be treated as if no module has been chosen. LSM modules must check now if they are allowed to register by calling security_module_enable(ops) first. Modify SELinux and SMACK to do so. Do not let SMACK register smackfs if it was not chosen on boot. Smackfs assumes that smack hooks are registered and the initial task security setup (swapper->security) is done. Signed-off-by: Ahmed S. Darwish Acked-by: James Morris --- Documentation/kernel-parameters.txt | 6 ++++++ include/linux/security.h | 12 ++++++++++++ security/dummy.c | 4 +++- security/security.c | 38 ++++++++++++++++++++++++++++++++++++- security/selinux/hooks.c | 7 +++++++ security/smack/smack.h | 2 ++ security/smack/smack_lsm.c | 7 ++++++- security/smack/smackfs.c | 11 ++++++++++- 8 files changed, 83 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 256a2162503c..4b0f1ae31a4c 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -366,6 +366,12 @@ and is between 256 and 4096 characters. It is defined in the file possible to determine what the correct size should be. This option provides an override for these situations. + security= [SECURITY] Choose a security module to enable at boot. + If this boot parameter is not specified, only the first + security module asking for security registration will be + loaded. An invalid security module name will be treated + as if no module has been chosen. + capability.disable= [SECURITY] Disable capabilities. This would normally be used only if an alternative security model is to be diff --git a/include/linux/security.h b/include/linux/security.h index 697f228daf19..f4116d6ed64b 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -36,6 +36,9 @@ extern unsigned securebits; +/* Maximum number of letters for an LSM name string */ +#define SECURITY_NAME_MAX 10 + struct ctl_table; struct audit_krule; @@ -137,6 +140,12 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) /** * struct security_operations - main security structure * + * Security module identifier. + * + * @name: + * A string that acts as a unique identifeir for the LSM with max number + * of characters = SECURITY_NAME_MAX. + * * Security hooks for program execution operations. * * @bprm_alloc_security: @@ -1270,6 +1279,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts) * This is the main security structure. */ struct security_operations { + char name[SECURITY_NAME_MAX + 1]; + int (*ptrace) (struct task_struct * parent, struct task_struct * child); int (*capget) (struct task_struct * target, kernel_cap_t * effective, @@ -1537,6 +1548,7 @@ struct security_operations { /* prototypes */ extern int security_init (void); +extern int security_module_enable(struct security_operations *ops); extern int register_security (struct security_operations *ops); extern int mod_reg_security (const char *name, struct security_operations *ops); extern struct dentry *securityfs_create_file(const char *name, mode_t mode, diff --git a/security/dummy.c b/security/dummy.c index 1ac9f8e66aa2..d797a4196b89 100644 --- a/security/dummy.c +++ b/security/dummy.c @@ -1017,7 +1017,9 @@ static inline void dummy_audit_rule_free(void *lsmrule) #endif /* CONFIG_AUDIT */ -struct security_operations dummy_security_ops; +struct security_operations dummy_security_ops = { + .name = "dummy", +}; #define set_to_dummy_if_null(ops, function) \ do { \ diff --git a/security/security.c b/security/security.c index 2ef593ec70f3..dd0c6baed494 100644 --- a/security/security.c +++ b/security/security.c @@ -17,6 +17,8 @@ #include #include +/* Boot-time LSM user choice */ +static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1]; /* things that live in dummy.c */ extern struct security_operations dummy_security_ops; @@ -67,13 +69,47 @@ int __init security_init(void) return 0; } +/* Save user chosen LSM */ +static int __init choose_lsm(char *str) +{ + strncpy(chosen_lsm, str, SECURITY_NAME_MAX); + return 1; +} +__setup("security=", choose_lsm); + +/** + * security_module_enable - Load given security module on boot ? + * @ops: a pointer to the struct security_operations that is to be checked. + * + * Each LSM must pass this method before registering its own operations + * to avoid security registration races. This method may also be used + * to check if your LSM is currently loaded. + * + * Return true if: + * -The passed LSM is the one chosen by user at boot time, + * -or user didsn't specify a specific LSM and we're the first to ask + * for registeration permissoin, + * -or the passed LSM is currently loaded. + * Otherwise, return false. + */ +int __init security_module_enable(struct security_operations *ops) +{ + if (!*chosen_lsm) + strncpy(chosen_lsm, ops->name, SECURITY_NAME_MAX); + else if (strncmp(ops->name, chosen_lsm, SECURITY_NAME_MAX)) + return 0; + + return 1; +} + /** * register_security - registers a security framework with the kernel * @ops: a pointer to the struct security_options that is to be registered * * This function is to allow a security module to register itself with the * kernel security subsystem. Some rudimentary checking is done on the @ops - * value passed to this function. + * value passed to this function. You'll need to check first if your LSM + * is allowed to register its @ops by calling security_module_enable(@ops). * * If there is already a security module registered with the kernel, * an error will be returned. Otherwise 0 is returned on success. diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index a2f7e9cf78c5..f9927f02bc3d 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -5295,6 +5295,8 @@ static int selinux_key_permission(key_ref_t key_ref, #endif static struct security_operations selinux_ops = { + .name = "selinux", + .ptrace = selinux_ptrace, .capget = selinux_capget, .capset_check = selinux_capset_check, @@ -5492,6 +5494,11 @@ static __init int selinux_init(void) { struct task_security_struct *tsec; + if (!security_module_enable(&selinux_ops)) { + selinux_enabled = 0; + return 0; + } + if (!selinux_enabled) { printk(KERN_INFO "SELinux: Disabled at boot.\n"); return 0; diff --git a/security/smack/smack.h b/security/smack/smack.h index 62c1e982849d..4a4477f5afdc 100644 --- a/security/smack/smack.h +++ b/security/smack/smack.h @@ -15,6 +15,7 @@ #include #include +#include #include /* @@ -187,6 +188,7 @@ extern struct smack_known smack_known_star; extern struct smack_known smack_known_unset; extern struct smk_list_entry *smack_list; +extern struct security_operations smack_ops; /* * Stricly for CIPSO level manipulation. diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 732ba27923c4..904bdc01a12b 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -2424,7 +2424,9 @@ static void smack_release_secctx(char *secdata, u32 seclen) { } -static struct security_operations smack_ops = { +struct security_operations smack_ops = { + .name = "smack", + .ptrace = smack_ptrace, .capget = cap_capget, .capset_check = cap_capset_check, @@ -2557,6 +2559,9 @@ static struct security_operations smack_ops = { */ static __init int smack_init(void) { + if (!security_module_enable(&smack_ops)) + return 0; + printk(KERN_INFO "Smack: Initializing.\n"); /* diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c index cfae8afcc262..6ba283783b70 100644 --- a/security/smack/smackfs.c +++ b/security/smack/smackfs.c @@ -965,12 +965,21 @@ static struct vfsmount *smackfs_mount; * * register the smackfs * - * Returns 0 unless the registration fails. + * Do not register smackfs if Smack wasn't enabled + * on boot. We can not put this method normally under the + * smack_init() code path since the security subsystem get + * initialized before the vfs caches. + * + * Returns true if we were not chosen on boot or if + * we were chosen and filesystem registration succeeded. */ static int __init init_smk_fs(void) { int err; + if (!security_module_enable(&smack_ops)) + return 0; + err = register_filesystem(&smk_fs_type); if (!err) { smackfs_mount = kern_mount(&smk_fs_type); -- cgit v1.2.3 From 6188e10d38b8d7244ee7776d5f1f88c837b4b93f Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 18 Apr 2008 22:21:05 -0400 Subject: Convert asm/semaphore.h users to linux/semaphore.h Signed-off-by: Matthew Wilcox --- Documentation/DocBook/kernel-locking.tmpl | 6 +++--- arch/ia64/kernel/salinfo.c | 2 +- drivers/base/core.c | 2 +- drivers/char/snsc.h | 2 +- drivers/firewire/fw-device.c | 3 ++- drivers/i2c/i2c-core.c | 2 +- drivers/ieee1394/nodemgr.c | 2 +- drivers/infiniband/core/user_mad.c | 2 +- drivers/infiniband/hw/mthca/mthca_dev.h | 3 +-- drivers/input/serio/hp_sdc_mlc.c | 2 +- drivers/macintosh/adb.c | 2 +- drivers/macintosh/windfarm_smu_sat.c | 2 +- drivers/net/3c527.c | 2 +- drivers/net/hamradio/6pack.c | 2 +- drivers/s390/cio/qdio.c | 2 +- drivers/scsi/aacraid/commctrl.c | 2 +- drivers/scsi/aacraid/commsup.c | 2 +- drivers/scsi/aacraid/dpcsup.c | 2 +- drivers/scsi/megaraid/megaraid_ioctl.h | 2 +- drivers/scsi/qla2xxx/qla_def.h | 2 +- drivers/watchdog/sc1200wdt.c | 2 +- fs/jffs2/jffs2_fs_i.h | 2 +- fs/jffs2/jffs2_fs_sb.h | 2 +- fs/reiserfs/journal.c | 2 +- fs/xfs/linux-2.6/sema.h | 2 +- include/linux/device.h | 2 +- include/linux/fs.h | 2 +- include/linux/hil_mlc.h | 2 +- include/linux/i2o.h | 2 +- include/linux/memory.h | 3 +-- include/linux/parport.h | 2 +- lib/kernel_lock.c | 2 +- 32 files changed, 35 insertions(+), 36 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl index 2e9d6b41f034..435413ca40dc 100644 --- a/Documentation/DocBook/kernel-locking.tmpl +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -241,7 +241,7 @@ The third type is a semaphore - (include/asm/semaphore.h): it + (include/linux/semaphore.h): it can have more than one holder at any time (the number decided at initialization time), although it is most commonly used as a single-holder lock (a mutex). If you can't get a semaphore, your @@ -290,7 +290,7 @@ If you have a data structure which is only ever accessed from user context, then you can use a simple semaphore - (linux/asm/semaphore.h) to protect it. This + (linux/linux/semaphore.h) to protect it. This is the most trivial case: you initialize the semaphore to the number of resources available (usually 1), and call down_interruptible() to grab the semaphore, and @@ -1656,7 +1656,7 @@ the amount of locking which needs to be done. #include <linux/slab.h> #include <linux/string.h> +#include <linux/rcupdate.h> - #include <asm/semaphore.h> + #include <linux/semaphore.h> #include <asm/errno.h> struct object diff --git a/arch/ia64/kernel/salinfo.c b/arch/ia64/kernel/salinfo.c index 779c3cca206c..b11bb50a197a 100644 --- a/arch/ia64/kernel/salinfo.c +++ b/arch/ia64/kernel/salinfo.c @@ -44,8 +44,8 @@ #include #include #include +#include -#include #include #include diff --git a/drivers/base/core.c b/drivers/base/core.c index 24198ad01976..7c4b36ccb1a0 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include "base.h" #include "power/power.h" diff --git a/drivers/char/snsc.h b/drivers/char/snsc.h index 8a98169b60c1..4be62eda9fbc 100644 --- a/drivers/char/snsc.h +++ b/drivers/char/snsc.h @@ -22,8 +22,8 @@ #include #include #include +#include #include -#include #define CHUNKSIZE 127 diff --git a/drivers/firewire/fw-device.c b/drivers/firewire/fw-device.c index 2d01bc1b9752..d9c8daf7ae7d 100644 --- a/drivers/firewire/fw-device.c +++ b/drivers/firewire/fw-device.c @@ -26,7 +26,8 @@ #include #include #include -#include +#include +#include #include #include #include "fw-transaction.h" diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 8b645c6b2cb5..e186df657119 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -35,8 +35,8 @@ #include #include #include +#include #include -#include #include "i2c-core.h" diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c index 70afa3786f3f..29d833e71cbf 100644 --- a/drivers/ieee1394/nodemgr.c +++ b/drivers/ieee1394/nodemgr.c @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include "csr.h" #include "highlevel.h" diff --git a/drivers/infiniband/core/user_mad.c b/drivers/infiniband/core/user_mad.c index 4e915104ac4c..be953e87bf93 100644 --- a/drivers/infiniband/core/user_mad.c +++ b/drivers/infiniband/core/user_mad.c @@ -46,9 +46,9 @@ #include #include #include +#include #include -#include #include #include diff --git a/drivers/infiniband/hw/mthca/mthca_dev.h b/drivers/infiniband/hw/mthca/mthca_dev.h index 0e842e023400..7bc32f8e377e 100644 --- a/drivers/infiniband/hw/mthca/mthca_dev.h +++ b/drivers/infiniband/hw/mthca/mthca_dev.h @@ -46,8 +46,7 @@ #include #include #include - -#include +#include #include "mthca_provider.h" #include "mthca_doorbell.h" diff --git a/drivers/input/serio/hp_sdc_mlc.c b/drivers/input/serio/hp_sdc_mlc.c index c45ea74d53e4..f1fd3b638a37 100644 --- a/drivers/input/serio/hp_sdc_mlc.c +++ b/drivers/input/serio/hp_sdc_mlc.c @@ -40,7 +40,7 @@ #include #include #include -#include +#include #define PREFIX "HP SDC MLC: " diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c index 28958101061f..20978205cd02 100644 --- a/drivers/macintosh/adb.c +++ b/drivers/macintosh/adb.c @@ -37,9 +37,9 @@ #include #include #include +#include #include -#include #ifdef CONFIG_PPC #include #include diff --git a/drivers/macintosh/windfarm_smu_sat.c b/drivers/macintosh/windfarm_smu_sat.c index f449d775cdf4..797918d0e59c 100644 --- a/drivers/macintosh/windfarm_smu_sat.c +++ b/drivers/macintosh/windfarm_smu_sat.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/drivers/net/3c527.c b/drivers/net/3c527.c index b72b89d53ec8..fae295b6809c 100644 --- a/drivers/net/3c527.c +++ b/drivers/net/3c527.c @@ -103,8 +103,8 @@ DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Procter #include #include +#include -#include #include #include #include diff --git a/drivers/net/hamradio/6pack.c b/drivers/net/hamradio/6pack.c index 0a9b75139e0f..1da55dd2a5a0 100644 --- a/drivers/net/hamradio/6pack.c +++ b/drivers/net/hamradio/6pack.c @@ -33,7 +33,7 @@ #include #include #include -#include +#include #include #define SIXPACK_VERSION "Revision: 0.3.0" diff --git a/drivers/s390/cio/qdio.c b/drivers/s390/cio/qdio.c index c359386708e9..10aa1e780801 100644 --- a/drivers/s390/cio/qdio.c +++ b/drivers/s390/cio/qdio.c @@ -38,11 +38,11 @@ #include #include #include +#include #include #include #include -#include #include #include diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c index abef05146d75..5fd83deab36c 100644 --- a/drivers/scsi/aacraid/commctrl.c +++ b/drivers/scsi/aacraid/commctrl.c @@ -39,7 +39,7 @@ #include #include /* ssleep prototype */ #include -#include +#include #include #include "aacraid.h" diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c index 23a8e9f8dcb4..ef67816a6fe5 100644 --- a/drivers/scsi/aacraid/commsup.c +++ b/drivers/scsi/aacraid/commsup.c @@ -41,11 +41,11 @@ #include #include #include +#include #include #include #include #include -#include #include "aacraid.h" diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c index d1163ded132b..933f208eedba 100644 --- a/drivers/scsi/aacraid/dpcsup.c +++ b/drivers/scsi/aacraid/dpcsup.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #include "aacraid.h" diff --git a/drivers/scsi/megaraid/megaraid_ioctl.h b/drivers/scsi/megaraid/megaraid_ioctl.h index 706fa05a187a..05f6e4ec3453 100644 --- a/drivers/scsi/megaraid/megaraid_ioctl.h +++ b/drivers/scsi/megaraid/megaraid_ioctl.h @@ -18,7 +18,7 @@ #define _MEGARAID_IOCTL_H_ #include -#include +#include #include "mbox_defs.h" diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h index 094d95f0764c..299eccf6cabd 100644 --- a/drivers/scsi/qla2xxx/qla_def.h +++ b/drivers/scsi/qla2xxx/qla_def.h @@ -25,7 +25,7 @@ #include #include #include -#include +#include #include #include diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 32ccd7c89c7d..35cddff7020f 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c @@ -38,8 +38,8 @@ #include #include #include +#include -#include #include #include diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h index 0b78fdc9773b..a841f4973a74 100644 --- a/fs/jffs2/jffs2_fs_i.h +++ b/fs/jffs2/jffs2_fs_i.h @@ -15,7 +15,7 @@ #include #include #include -#include +#include struct jffs2_inode_info { /* We need an internal mutex similar to inode->i_mutex. diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h index 3a2197f3c812..18fca2b9e531 100644 --- a/fs/jffs2/jffs2_fs_sb.h +++ b/fs/jffs2/jffs2_fs_sb.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include #include #include diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index bb05a3e51b93..060eb3f598e7 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -38,7 +38,7 @@ #include #include -#include +#include #include #include diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h index 2009e6d922ce..3abe7e9ceb33 100644 --- a/fs/xfs/linux-2.6/sema.h +++ b/fs/xfs/linux-2.6/sema.h @@ -20,8 +20,8 @@ #include #include +#include #include -#include /* * sema_t structure just maps to struct semaphore in Linux kernel. diff --git a/include/linux/device.h b/include/linux/device.h index 2258d89bf523..c79b93e56fa0 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -20,7 +20,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/linux/fs.h b/include/linux/fs.h index b84b848431f2..91e8dec9e42b 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -287,9 +287,9 @@ extern int dir_notify_enable; #include #include #include +#include #include -#include #include struct export_operations; diff --git a/include/linux/hil_mlc.h b/include/linux/hil_mlc.h index 8df29ca48a13..394a8405dd74 100644 --- a/include/linux/hil_mlc.h +++ b/include/linux/hil_mlc.h @@ -34,7 +34,7 @@ #include #include #include -#include +#include #include #include diff --git a/include/linux/i2o.h b/include/linux/i2o.h index 7da5b98d90e6..e92170dda245 100644 --- a/include/linux/i2o.h +++ b/include/linux/i2o.h @@ -33,9 +33,9 @@ #include #include #include +#include /* Needed for MUTEX init macros */ #include -#include /* Needed for MUTEX init macros */ /* message queue empty */ #define I2O_QUEUE_EMPTY 0xffffffff diff --git a/include/linux/memory.h b/include/linux/memory.h index 33f0ff0cf634..54d7866d9c0e 100644 --- a/include/linux/memory.h +++ b/include/linux/memory.h @@ -18,8 +18,7 @@ #include #include #include - -#include +#include struct memory_block { unsigned long phys_index; diff --git a/include/linux/parport.h b/include/linux/parport.h index d1ad546c8c9e..dcb9e01a69ca 100644 --- a/include/linux/parport.h +++ b/include/linux/parport.h @@ -101,9 +101,9 @@ typedef enum { #include #include #include +#include #include #include -#include /* Define this later. */ struct parport; diff --git a/lib/kernel_lock.c b/lib/kernel_lock.c index fbc11a336bc5..cd3e82530b03 100644 --- a/lib/kernel_lock.c +++ b/lib/kernel_lock.c @@ -8,7 +8,7 @@ #include #include #include -#include +#include /* * The 'big kernel semaphore' -- cgit v1.2.3 From f5a1b191b37ac2609e2babeec1b21f411da93e4d Mon Sep 17 00:00:00 2001 From: Jiri Slaby Date: Sat, 12 Apr 2008 10:28:25 +0200 Subject: x86: fix exec mappings comments - noexec32 is on by default for years already - add noexec32 to kernel-parameters and fix noexec typo in there Signed-off-by: Jiri Slaby Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- Documentation/kernel-parameters.txt | 10 +++++++++- arch/x86/kernel/setup64.c | 4 ++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4b0f1ae31a4c..f4839606988b 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1280,8 +1280,16 @@ and is between 256 and 4096 characters. It is defined in the file noexec [IA-64] noexec [X86-32,X86-64] + On X86-32 available only on PAE configured kernels. noexec=on: enable non-executable mappings (default) - noexec=off: disable nn-executable mappings + noexec=off: disable non-executable mappings + + noexec32 [X86-64] + This affects only 32-bit executables. + noexec32=on: enable non-executable mappings (default) + read doesn't imply executable mappings + noexec32=off: disable non-executable mappings + read implies executable mappings nofxsr [BUGS=X86-32] Disables x86 floating point extended register save and restore. The kernel will only save diff --git a/arch/x86/kernel/setup64.c b/arch/x86/kernel/setup64.c index 9042fb0e36f5..aee0e8200777 100644 --- a/arch/x86/kernel/setup64.c +++ b/arch/x86/kernel/setup64.c @@ -74,8 +74,8 @@ int force_personality32 = 0; Control non executable heap for 32bit processes. To control the stack too use noexec=off -on PROT_READ does not imply PROT_EXEC for 32bit processes -off PROT_READ implies PROT_EXEC (default) +on PROT_READ does not imply PROT_EXEC for 32bit processes (default) +off PROT_READ implies PROT_EXEC */ static int __init nonx32_setup(char *str) { -- cgit v1.2.3 From f1326973262382150c26bf4dfccd0fce310c4a9c Mon Sep 17 00:00:00 2001 From: Erik Bosman Date: Fri, 11 Apr 2008 18:57:22 +0200 Subject: generic, x86: add tests for prctl PR_GET_TSC and PR_SET_TSC This patch adds three tests that test whether the PR_GET_TSC and PR_SET_TSC commands have the desirable effect. The tests check whether the control register is updated correctly at context switches and try to discover bugs while enabling/disabling the timestamp counter. Signed-off-by: Erik Bosman Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- .../prctl/disable-tsc-ctxt-sw-stress-test.c | 96 ++++++++++++++++++++++ .../prctl/disable-tsc-on-off-stress-test.c | 95 +++++++++++++++++++++ Documentation/prctl/disable-tsc-test.c | 94 +++++++++++++++++++++ 3 files changed, 285 insertions(+) create mode 100644 Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c create mode 100644 Documentation/prctl/disable-tsc-on-off-stress-test.c create mode 100644 Documentation/prctl/disable-tsc-test.c (limited to 'Documentation') diff --git a/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c b/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c new file mode 100644 index 000000000000..f8e8e95e81fd --- /dev/null +++ b/Documentation/prctl/disable-tsc-ctxt-sw-stress-test.c @@ -0,0 +1,96 @@ +/* + * Tests for prctl(PR_GET_TSC, ...) / prctl(PR_SET_TSC, ...) + * + * Tests if the control register is updated correctly + * at context switches + * + * Warning: this test will cause a very high load for a few seconds + * + */ + +#include +#include +#include +#include +#include +#include + + +#include +#include + +/* Get/set the process' ability to use the timestamp counter instruction */ +#ifndef PR_GET_TSC +#define PR_GET_TSC 25 +#define PR_SET_TSC 26 +# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */ +# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */ +#endif + +uint64_t rdtsc() { +uint32_t lo, hi; +/* We cannot use "=A", since this would use %rax on x86_64 */ +__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); +return (uint64_t)hi << 32 | lo; +} + +void sigsegv_expect(int sig) +{ + /* */ +} + +void segvtask(void) +{ + if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0) + { + perror("prctl"); + exit(0); + } + signal(SIGSEGV, sigsegv_expect); + alarm(10); + rdtsc(); + fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n"); + exit(0); +} + + +void sigsegv_fail(int sig) +{ + fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n"); + exit(0); +} + +void rdtsctask(void) +{ + if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0) + { + perror("prctl"); + exit(0); + } + signal(SIGSEGV, sigsegv_fail); + alarm(10); + for(;;) rdtsc(); +} + + +int main(int argc, char **argv) +{ + int n_tasks = 100, i; + + fprintf(stderr, "[No further output means we're allright]\n"); + + for (i=0; i +#include +#include +#include +#include +#include + + +#include +#include + +/* Get/set the process' ability to use the timestamp counter instruction */ +#ifndef PR_GET_TSC +#define PR_GET_TSC 25 +#define PR_SET_TSC 26 +# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */ +# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */ +#endif + +/* snippet from wikipedia :-) */ + +uint64_t rdtsc() { +uint32_t lo, hi; +/* We cannot use "=A", since this would use %rax on x86_64 */ +__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); +return (uint64_t)hi << 32 | lo; +} + +int should_segv = 0; + +void sigsegv_cb(int sig) +{ + if (!should_segv) + { + fprintf(stderr, "FATAL ERROR, rdtsc() failed while enabled\n"); + exit(0); + } + if (prctl(PR_SET_TSC, PR_TSC_ENABLE) < 0) + { + perror("prctl"); + exit(0); + } + should_segv = 0; + + rdtsc(); +} + +void task(void) +{ + signal(SIGSEGV, sigsegv_cb); + alarm(10); + for(;;) + { + rdtsc(); + if (should_segv) + { + fprintf(stderr, "FATAL ERROR, rdtsc() succeeded while disabled\n"); + exit(0); + } + if (prctl(PR_SET_TSC, PR_TSC_SIGSEGV) < 0) + { + perror("prctl"); + exit(0); + } + should_segv = 1; + } +} + + +int main(int argc, char **argv) +{ + int n_tasks = 100, i; + + fprintf(stderr, "[No further output means we're allright]\n"); + + for (i=0; i +#include +#include +#include +#include + + +#include +#include + +/* Get/set the process' ability to use the timestamp counter instruction */ +#ifndef PR_GET_TSC +#define PR_GET_TSC 25 +#define PR_SET_TSC 26 +# define PR_TSC_ENABLE 1 /* allow the use of the timestamp counter */ +# define PR_TSC_SIGSEGV 2 /* throw a SIGSEGV instead of reading the TSC */ +#endif + +const char *tsc_names[] = +{ + [0] = "[not set]", + [PR_TSC_ENABLE] = "PR_TSC_ENABLE", + [PR_TSC_SIGSEGV] = "PR_TSC_SIGSEGV", +}; + +uint64_t rdtsc() { +uint32_t lo, hi; +/* We cannot use "=A", since this would use %rax on x86_64 */ +__asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); +return (uint64_t)hi << 32 | lo; +} + +void sigsegv_cb(int sig) +{ + int tsc_val = 0; + + printf("[ SIG_SEGV ]\n"); + printf("prctl(PR_GET_TSC, &tsc_val); "); + fflush(stdout); + + if ( prctl(PR_GET_TSC, &tsc_val) == -1) + perror("prctl"); + + printf("tsc_val == %s\n", tsc_names[tsc_val]); + printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n"); + fflush(stdout); + if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1) + perror("prctl"); + + printf("rdtsc() == "); +} + +int main(int argc, char **argv) +{ + int tsc_val = 0; + + signal(SIGSEGV, sigsegv_cb); + + printf("rdtsc() == %llu\n", (unsigned long long)rdtsc()); + printf("prctl(PR_GET_TSC, &tsc_val); "); + fflush(stdout); + + if ( prctl(PR_GET_TSC, &tsc_val) == -1) + perror("prctl"); + + printf("tsc_val == %s\n", tsc_names[tsc_val]); + printf("rdtsc() == %llu\n", (unsigned long long)rdtsc()); + printf("prctl(PR_SET_TSC, PR_TSC_ENABLE)\n"); + fflush(stdout); + + if ( prctl(PR_SET_TSC, PR_TSC_ENABLE) == -1) + perror("prctl"); + + printf("rdtsc() == %llu\n", (unsigned long long)rdtsc()); + printf("prctl(PR_SET_TSC, PR_TSC_SIGSEGV)\n"); + fflush(stdout); + + if ( prctl(PR_SET_TSC, PR_TSC_SIGSEGV) == -1) + perror("prctl"); + + printf("rdtsc() == "); + fflush(stdout); + printf("%llu\n", (unsigned long long)rdtsc()); + fflush(stdout); + + exit(EXIT_SUCCESS); +} + -- cgit v1.2.3 From fae9a0d8ca68a14da8d2351ad3e0bf42f3b29899 Mon Sep 17 00:00:00 2001 From: Glauber Costa Date: Tue, 8 Apr 2008 13:20:56 -0300 Subject: x86: merge iommu initialization parameters we merge the iommu initialization parameters in pci-dma.c Nice thing, that both architectures at least recognize the same parameters. usedac i386 parameter is marked for deprecation Signed-off-by: Glauber Costa Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- Documentation/feature-removal-schedule.txt | 7 +++ arch/x86/kernel/pci-dma.c | 81 ++++++++++++++++++++++++++++++ arch/x86/kernel/pci-dma_32.c | 12 ----- arch/x86/kernel/pci-dma_64.c | 79 ----------------------------- include/asm-x86/dma-mapping.h | 1 + 5 files changed, 89 insertions(+), 91 deletions(-) (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index af0e9393bf68..309c47b91598 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -282,6 +282,13 @@ Why: Not used in-tree. The current out-of-tree users used it to out-of-tree driver. Who: Thomas Gleixner +---------------------------- + +What: usedac i386 kernel parameter +When: 2.6.27 +Why: replaced by allowdac and no dac combination +Who: Glauber Costa + --------------------------- What: /sys/o2cb symlink diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c index 7d3bd652c36f..48ab52d052b6 100644 --- a/arch/x86/kernel/pci-dma.c +++ b/arch/x86/kernel/pci-dma.c @@ -24,6 +24,18 @@ int panic_on_overflow __read_mostly = 0; int force_iommu __read_mostly = 0; #endif +int iommu_merge __read_mostly = 0; + +int no_iommu __read_mostly; +/* Set this to 1 if there is a HW IOMMU in the system */ +int iommu_detected __read_mostly = 0; + +/* This tells the BIO block layer to assume merging. Default to off + because we cannot guarantee merging later. */ +int iommu_bio_merge __read_mostly = 0; +EXPORT_SYMBOL(iommu_bio_merge); + + int dma_set_mask(struct device *dev, u64 mask) { if (!dev->dma_mask || !dma_supported(dev, mask)) @@ -105,6 +117,75 @@ void __init pci_iommu_alloc(void) } #endif +/* + * See for the iommu kernel parameter + * documentation. + */ +static __init int iommu_setup(char *p) +{ + iommu_merge = 1; + + if (!p) + return -EINVAL; + + while (*p) { + if (!strncmp(p, "off", 3)) + no_iommu = 1; + /* gart_parse_options has more force support */ + if (!strncmp(p, "force", 5)) + force_iommu = 1; + if (!strncmp(p, "noforce", 7)) { + iommu_merge = 0; + force_iommu = 0; + } + + if (!strncmp(p, "biomerge", 8)) { + iommu_bio_merge = 4096; + iommu_merge = 1; + force_iommu = 1; + } + if (!strncmp(p, "panic", 5)) + panic_on_overflow = 1; + if (!strncmp(p, "nopanic", 7)) + panic_on_overflow = 0; + if (!strncmp(p, "merge", 5)) { + iommu_merge = 1; + force_iommu = 1; + } + if (!strncmp(p, "nomerge", 7)) + iommu_merge = 0; + if (!strncmp(p, "forcesac", 8)) + iommu_sac_force = 1; + if (!strncmp(p, "allowdac", 8)) + forbid_dac = 0; + if (!strncmp(p, "nodac", 5)) + forbid_dac = -1; + if (!strncmp(p, "usedac", 6)) { + forbid_dac = -1; + return 1; + } +#ifdef CONFIG_SWIOTLB + if (!strncmp(p, "soft", 4)) + swiotlb = 1; +#endif + +#ifdef CONFIG_GART_IOMMU + gart_parse_options(p); +#endif + +#ifdef CONFIG_CALGARY_IOMMU + if (!strncmp(p, "calgary", 7)) + use_calgary = 1; +#endif /* CONFIG_CALGARY_IOMMU */ + + p += strcspn(p, ","); + if (*p == ',') + ++p; + } + return 0; +} +early_param("iommu", iommu_setup); + int dma_supported(struct device *dev, u64 mask) { #ifdef CONFIG_PCI diff --git a/arch/x86/kernel/pci-dma_32.c b/arch/x86/kernel/pci-dma_32.c index 1d4091af4417..eea52df68a3b 100644 --- a/arch/x86/kernel/pci-dma_32.c +++ b/arch/x86/kernel/pci-dma_32.c @@ -153,15 +153,3 @@ void *dma_mark_declared_memory_occupied(struct device *dev, return mem->virt_base + (pos << PAGE_SHIFT); } EXPORT_SYMBOL(dma_mark_declared_memory_occupied); - -#ifdef CONFIG_PCI -static int check_iommu(char *s) -{ - if (!strcmp(s, "usedac")) { - forbid_dac = -1; - return 1; - } - return 0; -} -__setup("iommu=", check_iommu); -#endif diff --git a/arch/x86/kernel/pci-dma_64.c b/arch/x86/kernel/pci-dma_64.c index c80da76e7e61..e7d45cf82251 100644 --- a/arch/x86/kernel/pci-dma_64.c +++ b/arch/x86/kernel/pci-dma_64.c @@ -14,22 +14,9 @@ #include #include -int iommu_merge __read_mostly = 0; - dma_addr_t bad_dma_address __read_mostly; EXPORT_SYMBOL(bad_dma_address); -/* This tells the BIO block layer to assume merging. Default to off - because we cannot guarantee merging later. */ -int iommu_bio_merge __read_mostly = 0; -EXPORT_SYMBOL(iommu_bio_merge); - -extern int iommu_sac_force; - -int no_iommu __read_mostly; -/* Set this to 1 if there is a HW IOMMU in the system */ -int iommu_detected __read_mostly = 0; - /* Dummy device used for NULL arguments (normally ISA). Better would be probably a smaller DMA mask, but this is bug-to-bug compatible to i386. */ @@ -160,69 +147,3 @@ void dma_free_coherent(struct device *dev, size_t size, free_pages((unsigned long)vaddr, get_order(size)); } EXPORT_SYMBOL(dma_free_coherent); - -/* - * See for the iommu kernel parameter - * documentation. - */ -static __init int iommu_setup(char *p) -{ - iommu_merge = 1; - - if (!p) - return -EINVAL; - - while (*p) { - if (!strncmp(p, "off", 3)) - no_iommu = 1; - /* gart_parse_options has more force support */ - if (!strncmp(p, "force", 5)) - force_iommu = 1; - if (!strncmp(p, "noforce", 7)) { - iommu_merge = 0; - force_iommu = 0; - } - - if (!strncmp(p, "biomerge", 8)) { - iommu_bio_merge = 4096; - iommu_merge = 1; - force_iommu = 1; - } - if (!strncmp(p, "panic", 5)) - panic_on_overflow = 1; - if (!strncmp(p, "nopanic", 7)) - panic_on_overflow = 0; - if (!strncmp(p, "merge", 5)) { - iommu_merge = 1; - force_iommu = 1; - } - if (!strncmp(p, "nomerge", 7)) - iommu_merge = 0; - if (!strncmp(p, "forcesac", 8)) - iommu_sac_force = 1; - if (!strncmp(p, "allowdac", 8)) - forbid_dac = 0; - if (!strncmp(p, "nodac", 5)) - forbid_dac = -1; - -#ifdef CONFIG_SWIOTLB - if (!strncmp(p, "soft", 4)) - swiotlb = 1; -#endif - -#ifdef CONFIG_GART_IOMMU - gart_parse_options(p); -#endif - -#ifdef CONFIG_CALGARY_IOMMU - if (!strncmp(p, "calgary", 7)) - use_calgary = 1; -#endif /* CONFIG_CALGARY_IOMMU */ - - p += strcspn(p, ","); - if (*p == ',') - ++p; - } - return 0; -} -early_param("iommu", iommu_setup); diff --git a/include/asm-x86/dma-mapping.h b/include/asm-x86/dma-mapping.h index d82517de1e7c..75807368051a 100644 --- a/include/asm-x86/dma-mapping.h +++ b/include/asm-x86/dma-mapping.h @@ -15,6 +15,7 @@ extern int iommu_merge; extern struct device fallback_dev; extern int panic_on_overflow; extern int forbid_dac; +extern int force_iommu; struct dma_mapping_ops { int (*mapping_error)(dma_addr_t dma_addr); -- cgit v1.2.3 From 4d5f35533fb9b2cd553cec6611195bcbfb7ffd84 Mon Sep 17 00:00:00 2001 From: Hidetoshi Seto Date: Tue, 15 Apr 2008 14:03:17 +0900 Subject: sched, cpuset: customize sched domains, docs This patch introduces new feature of cpuset - sched domain customization. This version provides a per-cpuset file 'sched_relax_domain_level' that enable us to change the searching range of scheduler, which used to limit how many cpus the scheduler searches at some schedule events, such as wakening task and running out of runqueue. Signed-off-by: Hidetoshi Seto Signed-off-by: Ingo Molnar --- Documentation/cpusets.txt | 72 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/cpusets.txt b/Documentation/cpusets.txt index ad2bb3b3acc1..aa854b9b18cd 100644 --- a/Documentation/cpusets.txt +++ b/Documentation/cpusets.txt @@ -8,6 +8,7 @@ Portions Copyright (c) 2004-2006 Silicon Graphics, Inc. Modified by Paul Jackson Modified by Christoph Lameter Modified by Paul Menage +Modified by Hidetoshi Seto CONTENTS: ========= @@ -20,7 +21,8 @@ CONTENTS: 1.5 What is memory_pressure ? 1.6 What is memory spread ? 1.7 What is sched_load_balance ? - 1.8 How do I use cpusets ? + 1.8 What is sched_relax_domain_level ? + 1.9 How do I use cpusets ? 2. Usage Examples and Syntax 2.1 Basic Usage 2.2 Adding/removing cpus @@ -497,7 +499,73 @@ the cpuset code to update these sched domains, it compares the new partition requested with the current, and updates its sched domains, removing the old and adding the new, for each change. -1.8 How do I use cpusets ? + +1.8 What is sched_relax_domain_level ? +-------------------------------------- + +In sched domain, the scheduler migrates tasks in 2 ways; periodic load +balance on tick, and at time of some schedule events. + +When a task is woken up, scheduler try to move the task on idle CPU. +For example, if a task A running on CPU X activates another task B +on the same CPU X, and if CPU Y is X's sibling and performing idle, +then scheduler migrate task B to CPU Y so that task B can start on +CPU Y without waiting task A on CPU X. + +And if a CPU run out of tasks in its runqueue, the CPU try to pull +extra tasks from other busy CPUs to help them before it is going to +be idle. + +Of course it takes some searching cost to find movable tasks and/or +idle CPUs, the scheduler might not search all CPUs in the domain +everytime. In fact, in some architectures, the searching ranges on +events are limited in the same socket or node where the CPU locates, +while the load balance on tick searchs all. + +For example, assume CPU Z is relatively far from CPU X. Even if CPU Z +is idle while CPU X and the siblings are busy, scheduler can't migrate +woken task B from X to Z since it is out of its searching range. +As the result, task B on CPU X need to wait task A or wait load balance +on the next tick. For some applications in special situation, waiting +1 tick may be too long. + +The 'sched_relax_domain_level' file allows you to request changing +this searching range as you like. This file takes int value which +indicates size of searching range in levels ideally as follows, +otherwise initial value -1 that indicates the cpuset has no request. + + -1 : no request. use system default or follow request of others. + 0 : no search. + 1 : search siblings (hyperthreads in a core). + 2 : search cores in a package. + 3 : search cpus in a node [= system wide on non-NUMA system] + ( 4 : search nodes in a chunk of node [on NUMA system] ) + ( 5~ : search system wide [on NUMA system]) + +This file is per-cpuset and affect the sched domain where the cpuset +belongs to. Therefore if the flag 'sched_load_balance' of a cpuset +is disabled, then 'sched_relax_domain_level' have no effect since +there is no sched domain belonging the cpuset. + +If multiple cpusets are overlapping and hence they form a single sched +domain, the largest value among those is used. Be careful, if one +requests 0 and others are -1 then 0 is used. + +Note that modifying this file will have both good and bad effects, +and whether it is acceptable or not will be depend on your situation. +Don't modify this file if you are not sure. + +If your situation is: + - The migration costs between each cpu can be assumed considerably + small(for you) due to your special application's behavior or + special hardware support for CPU cache etc. + - The searching cost doesn't have impact(for you) or you can make + the searching cost enough small by managing cpuset to compact etc. + - The latency is required even it sacrifices cache hit rate etc. +then increasing 'sched_relax_domain_level' would benefit you. + + +1.9 How do I use cpusets ? -------------------------- In order to minimize the impact of cpusets on critical kernel -- cgit v1.2.3 From b9b158fe1ca2c166ff918de30cb098eafcae487a Mon Sep 17 00:00:00 2001 From: Viktor Radnai Date: Sat, 19 Apr 2008 19:45:01 +0200 Subject: sched: better rt-group documentation Viktor was nice enough to enhance the document based on my replies to his questions on the subject. Signed-off-by: Peter Zijlstra Signed-off-by: Ingo Molnar --- Documentation/scheduler/sched-rt-group.txt | 188 +++++++++++++++++++++++------ init/Kconfig | 7 ++ 2 files changed, 160 insertions(+), 35 deletions(-) (limited to 'Documentation') diff --git a/Documentation/scheduler/sched-rt-group.txt b/Documentation/scheduler/sched-rt-group.txt index 1c6332f4543c..14f901f639ee 100644 --- a/Documentation/scheduler/sched-rt-group.txt +++ b/Documentation/scheduler/sched-rt-group.txt @@ -1,59 +1,177 @@ + Real-Time group scheduling + -------------------------- +CONTENTS +======== -Real-Time group scheduling. +1. Overview + 1.1 The problem + 1.2 The solution +2. The interface + 2.1 System-wide settings + 2.2 Default behaviour + 2.3 Basis for grouping tasks +3. Future plans -The problem space: -In order to schedule multiple groups of realtime tasks each group must -be assigned a fixed portion of the CPU time available. Without a minimum -guarantee a realtime group can obviously fall short. A fuzzy upper limit -is of no use since it cannot be relied upon. Which leaves us with just -the single fixed portion. +1. Overview +=========== -CPU time is divided by means of specifying how much time can be spent -running in a given period. Say a frame fixed realtime renderer must -deliver 25 frames a second, which yields a period of 0.04s. Now say -it will also have to play some music and respond to input, leaving it -with around 80% for the graphics. We can then give this group a runtime -of 0.8 * 0.04s = 0.032s. -This way the graphics group will have a 0.04s period with a 0.032s runtime -limit. +1.1 The problem +--------------- -Now if the audio thread needs to refill the DMA buffer every 0.005s, but -needs only about 3% CPU time to do so, it can do with a 0.03 * 0.005s -= 0.00015s. +Realtime scheduling is all about determinism, a group has to be able to rely on +the amount of bandwidth (eg. CPU time) being constant. In order to schedule +multiple groups of realtime tasks, each group must be assigned a fixed portion +of the CPU time available. Without a minimum guarantee a realtime group can +obviously fall short. A fuzzy upper limit is of no use since it cannot be +relied upon. Which leaves us with just the single fixed portion. +1.2 The solution +---------------- -The Interface: +CPU time is divided by means of specifying how much time can be spent running +in a given period. We allocate this "run time" for each realtime group which +the other realtime groups will not be permitted to use. -system wide: +Any time not allocated to a realtime group will be used to run normal priority +tasks (SCHED_OTHER). Any allocated run time not used will also be picked up by +SCHED_OTHER. -/proc/sys/kernel/sched_rt_period_ms -/proc/sys/kernel/sched_rt_runtime_us +Let's consider an example: a frame fixed realtime renderer must deliver 25 +frames a second, which yields a period of 0.04s per frame. Now say it will also +have to play some music and respond to input, leaving it with around 80% CPU +time dedicated for the graphics. We can then give this group a run time of 0.8 +* 0.04s = 0.032s. -CONFIG_FAIR_USER_SCHED +This way the graphics group will have a 0.04s period with a 0.032s run time +limit. Now if the audio thread needs to refill the DMA buffer every 0.005s, but +needs only about 3% CPU time to do so, it can do with a 0.03 * 0.005s = +0.00015s. So this group can be scheduled with a period of 0.005s and a run time +of 0.00015s. -/sys/kernel/uids//cpu_rt_runtime_us +The remaining CPU time will be used for user input and other tass. Because +realtime tasks have explicitly allocated the CPU time they need to perform +their tasks, buffer underruns in the graphocs or audio can be eliminated. -or +NOTE: the above example is not fully implemented as of yet (2.6.25). We still +lack an EDF scheduler to make non-uniform periods usable. -CONFIG_FAIR_CGROUP_SCHED -/cgroup//cpu.rt_runtime_us +2. The Interface +================ -[ time is specified in us because the interface is s32; this gives an - operating range of ~35m to 1us ] -The period takes values in [ 1, INT_MAX ], runtime in [ -1, INT_MAX - 1 ]. +2.1 System wide settings +------------------------ -A runtime of -1 specifies runtime == period, ie. no limit. +The system wide settings are configured under the /proc virtual file system: -New groups get the period from /proc/sys/kernel/sched_rt_period_us and -a runtime of 0. +/proc/sys/kernel/sched_rt_period_us: + The scheduling period that is equivalent to 100% CPU bandwidth -Settings are constrained to: +/proc/sys/kernel/sched_rt_runtime_us: + A global limit on how much time realtime scheduling may use. Even without + CONFIG_RT_GROUP_SCHED enabled, this will limit time reserved to realtime + processes. With CONFIG_RT_GROUP_SCHED it signifies the total bandwidth + available to all realtime groups. + + * Time is specified in us because the interface is s32. This gives an + operating range from 1us to about 35 minutes. + * sched_rt_period_us takes values from 1 to INT_MAX. + * sched_rt_runtime_us takes values from -1 to (INT_MAX - 1). + * A run time of -1 specifies runtime == period, ie. no limit. + + +2.2 Default behaviour +--------------------- + +The default values for sched_rt_period_us (1000000 or 1s) and +sched_rt_runtime_us (950000 or 0.95s). This gives 0.05s to be used by +SCHED_OTHER (non-RT tasks). These defaults were chosen so that a run-away +realtime tasks will not lock up the machine but leave a little time to recover +it. By setting runtime to -1 you'd get the old behaviour back. + +By default all bandwidth is assigned to the root group and new groups get the +period from /proc/sys/kernel/sched_rt_period_us and a run time of 0. If you +want to assign bandwidth to another group, reduce the root group's bandwidth +and assign some or all of the difference to another group. + +Realtime group scheduling means you have to assign a portion of total CPU +bandwidth to the group before it will accept realtime tasks. Therefore you will +not be able to run realtime tasks as any user other than root until you have +done that, even if the user has the rights to run processes with realtime +priority! + + +2.3 Basis for grouping tasks +---------------------------- + +There are two compile-time settings for allocating CPU bandwidth. These are +configured using the "Basis for grouping tasks" multiple choice menu under +General setup > Group CPU Scheduler: + +a. CONFIG_USER_SCHED (aka "Basis for grouping tasks" = "user id") + +This lets you use the virtual files under +"/sys/kernel/uids//cpu_rt_runtime_us" to control he CPU time reserved for +each user . + +The other option is: + +.o CONFIG_CGROUP_SCHED (aka "Basis for grouping tasks" = "Control groups") + +This uses the /cgroup virtual file system and "/cgroup//cpu.rt_runtime_us" +to control the CPU time reserved for each control group instead. + +For more information on working with control groups, you should read +Documentation/cgroups.txt as well. + +Group settings are checked against the following limits in order to keep the configuration +schedulable: \Sum_{i} runtime_{i} / global_period <= global_runtime / global_period -in order to keep the configuration schedulable. +For now, this can be simplified to just the following (but see Future plans): + + \Sum_{i} runtime_{i} <= global_runtime + + +3. Future plans +=============== + +There is work in progress to make the scheduling period for each group +("/sys/kernel/uids//cpu_rt_period_us" or +"/cgroup//cpu.rt_period_us" respectively) configurable as well. + +The constraint on the period is that a subgroup must have a smaller or +equal period to its parent. But realistically its not very useful _yet_ +as its prone to starvation without deadline scheduling. + +Consider two sibling groups A and B; both have 50% bandwidth, but A's +period is twice the length of B's. + +* group A: period=100000us, runtime=10000us + - this runs for 0.01s once every 0.1s + +* group B: period= 50000us, runtime=10000us + - this runs for 0.01s twice every 0.1s (or once every 0.05 sec). + +This means that currently a while (1) loop in A will run for the full period of +B and can starve B's tasks (assuming they are of lower priority) for a whole +period. + +The next project will be SCHED_EDF (Earliest Deadline First scheduling) to bring +full deadline scheduling to the linux kernel. Deadline scheduling the above +groups and treating end of the period as a deadline will ensure that they both +get their allocated time. + +Implementing SCHED_EDF might take a while to complete. Priority Inheritance is +the biggest challenge as the current linux PI infrastructure is geared towards +the limited static priority levels 0-139. With deadline scheduling you need to +do deadline inheritance (since priority is inversely proportional to the +deadline delta (deadline - now). + +This means the whole PI machinery will have to be reworked - and that is one of +the most complex pieces of code we have. diff --git a/init/Kconfig b/init/Kconfig index 7fccf09bb95a..ba3a389fab94 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -328,6 +328,13 @@ config RT_GROUP_SCHED depends on EXPERIMENTAL depends on GROUP_SCHED default n + help + This feature lets you explicitly allocate real CPU bandwidth + to users or control groups (depending on the "Basis for grouping tasks" + setting below. If enabled, it will also make it impossible to + schedule realtime tasks for non-root users until you allocate + realtime bandwidth for them. + See Documentation/sched-rt-group.txt for more information. choice depends on GROUP_SCHED -- cgit v1.2.3 From d2f5e80862d33a7746a40569840248a592dbc395 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 19 Apr 2008 13:49:34 -0400 Subject: Deprecate the asm/semaphore.h files in feature-removal-schedule. Signed-off-by: Matthew Wilcox --- Documentation/feature-removal-schedule.txt | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index af0e9393bf68..44ce6f607f25 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -291,3 +291,11 @@ Why: /sys/fs/o2cb is the proper location for this information - /sys/o2cb ocfs2-tools. 2 years should be sufficient time to phase in new versions which know to look in /sys/fs/o2cb. Who: ocfs2-devel@oss.oracle.com + +--------------------------- + +What: asm/semaphore.h +When: 2.6.26 +Why: Implementation became generic; users should now include + linux/semaphore.h instead. +Who: Matthew Wilcox -- cgit v1.2.3 From d289bf7bdd84d636054acb0b3d14a4708f8a8233 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Wed, 20 Feb 2008 13:20:50 -0800 Subject: firmware: move firmware_class from Documentation/ to samples/ Move the firmware_class sample drivers to samples/ so that they are buildable and can be maintained. Signed-off-by: Randy Dunlap Acked-by: Marcel Holtmann Signed-off-by: Greg Kroah-Hartman --- .../firmware_class/firmware_sample_driver.c | 115 ------------ .../firmware_sample_firmware_class.c | 207 --------------------- samples/firmware_class/firmware_sample_driver.c | 115 ++++++++++++ .../firmware_sample_firmware_class.c | 207 +++++++++++++++++++++ 4 files changed, 322 insertions(+), 322 deletions(-) delete mode 100644 Documentation/firmware_class/firmware_sample_driver.c delete mode 100644 Documentation/firmware_class/firmware_sample_firmware_class.c create mode 100644 samples/firmware_class/firmware_sample_driver.c create mode 100644 samples/firmware_class/firmware_sample_firmware_class.c (limited to 'Documentation') diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c deleted file mode 100644 index 6865cbe075ec..000000000000 --- a/Documentation/firmware_class/firmware_sample_driver.c +++ /dev/null @@ -1,115 +0,0 @@ -/* - * firmware_sample_driver.c - - * - * Copyright (c) 2003 Manuel Estrada Sainz - * - * Sample code on how to use request_firmware() from drivers. - * - */ - -#include -#include -#include -#include -#include - -#include "linux/firmware.h" - -static struct device ghost_device = { - .bus_id = "ghost0", -}; - - -static void sample_firmware_load(char *firmware, int size) -{ - u8 buf[size+1]; - memcpy(buf, firmware, size); - buf[size] = '\0'; - printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf); -} - -static void sample_probe_default(void) -{ - /* uses the default method to get the firmware */ - const struct firmware *fw_entry; - printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n"); - - if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0) - { - printk(KERN_ERR - "firmware_sample_driver: Firmware not available\n"); - return; - } - - sample_firmware_load(fw_entry->data, fw_entry->size); - - release_firmware(fw_entry); - - /* finish setting up the device */ -} -static void sample_probe_specific(void) -{ - /* Uses some specific hotplug support to get the firmware from - * userspace directly into the hardware, or via some sysfs file */ - - /* NOTE: This currently doesn't work */ - - printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n"); - - if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0) - { - printk(KERN_ERR - "firmware_sample_driver: Firmware load failed\n"); - return; - } - - /* request_firmware blocks until userspace finished, so at - * this point the firmware should be already in the device */ - - /* finish setting up the device */ -} -static void sample_probe_async_cont(const struct firmware *fw, void *context) -{ - if(!fw){ - printk(KERN_ERR - "firmware_sample_driver: firmware load failed\n"); - return; - } - - printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n", - (char *)context); - sample_firmware_load(fw->data, fw->size); -} -static void sample_probe_async(void) -{ - /* Let's say that I can't sleep */ - int error; - error = request_firmware_nowait (THIS_MODULE, FW_ACTION_NOHOTPLUG, - "sample_driver_fw", &ghost_device, - "my device pointer", - sample_probe_async_cont); - if(error){ - printk(KERN_ERR - "firmware_sample_driver:" - " request_firmware_nowait failed\n"); - } -} - -static int sample_init(void) -{ - device_initialize(&ghost_device); - /* since there is no real hardware insertion I just call the - * sample probe functions here */ - sample_probe_specific(); - sample_probe_default(); - sample_probe_async(); - return 0; -} -static void __exit sample_exit(void) -{ -} - -module_init (sample_init); -module_exit (sample_exit); - -MODULE_LICENSE("GPL"); diff --git a/Documentation/firmware_class/firmware_sample_firmware_class.c b/Documentation/firmware_class/firmware_sample_firmware_class.c deleted file mode 100644 index 2de62854f0e5..000000000000 --- a/Documentation/firmware_class/firmware_sample_firmware_class.c +++ /dev/null @@ -1,207 +0,0 @@ -/* - * firmware_sample_firmware_class.c - - * - * Copyright (c) 2003 Manuel Estrada Sainz - * - * NOTE: This is just a probe of concept, if you think that your driver would - * be well served by this mechanism please contact me first. - * - * DON'T USE THIS CODE AS IS - * - */ - -#include -#include -#include -#include -#include -#include -#include - - -MODULE_AUTHOR("Manuel Estrada Sainz"); -MODULE_DESCRIPTION("Hackish sample for using firmware class directly"); -MODULE_LICENSE("GPL"); - -static inline struct class_device *to_class_dev(struct kobject *obj) -{ - return container_of(obj,struct class_device,kobj); -} -static inline -struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) -{ - return container_of(_attr,struct class_device_attribute,attr); -} - -int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); -int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); - -struct firmware_priv { - char fw_id[FIRMWARE_NAME_MAX]; - s32 loading:2; - u32 abort:1; -}; - -extern struct class firmware_class; - -static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf) -{ - struct firmware_priv *fw_priv = class_get_devdata(class_dev); - return sprintf(buf, "%d\n", fw_priv->loading); -} -static ssize_t firmware_loading_store(struct class_device *class_dev, - const char *buf, size_t count) -{ - struct firmware_priv *fw_priv = class_get_devdata(class_dev); - int prev_loading = fw_priv->loading; - - fw_priv->loading = simple_strtol(buf, NULL, 10); - - switch(fw_priv->loading){ - case -1: - /* abort load an panic */ - break; - case 1: - /* setup load */ - break; - case 0: - if(prev_loading==1){ - /* finish load and get the device back to working - * state */ - } - break; - } - - return count; -} -static CLASS_DEVICE_ATTR(loading, 0644, - firmware_loading_show, firmware_loading_store); - -static ssize_t firmware_data_read(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t offset, size_t count) -{ - struct class_device *class_dev = to_class_dev(kobj); - struct firmware_priv *fw_priv = class_get_devdata(class_dev); - - /* read from the devices firmware memory */ - - return count; -} -static ssize_t firmware_data_write(struct kobject *kobj, - struct bin_attribute *bin_attr, - char *buffer, loff_t offset, size_t count) -{ - struct class_device *class_dev = to_class_dev(kobj); - struct firmware_priv *fw_priv = class_get_devdata(class_dev); - - /* write to the devices firmware memory */ - - return count; -} -static struct bin_attribute firmware_attr_data = { - .attr = {.name = "data", .mode = 0644}, - .size = 0, - .read = firmware_data_read, - .write = firmware_data_write, -}; -static int fw_setup_class_device(struct class_device *class_dev, - const char *fw_name, - struct device *device) -{ - int retval; - struct firmware_priv *fw_priv; - - fw_priv = kzalloc(sizeof(struct firmware_priv), GFP_KERNEL); - if (!fw_priv) { - retval = -ENOMEM; - goto out; - } - - memset(class_dev, 0, sizeof(*class_dev)); - - strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); - fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0'; - - strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE); - class_dev->class_id[BUS_ID_SIZE-1] = '\0'; - class_dev->dev = device; - - class_dev->class = &firmware_class, - class_set_devdata(class_dev, fw_priv); - retval = class_device_register(class_dev); - if (retval){ - printk(KERN_ERR "%s: class_device_register failed\n", - __FUNCTION__); - goto error_free_fw_priv; - } - - retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data); - if (retval){ - printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", - __FUNCTION__); - goto error_unreg_class_dev; - } - - retval = class_device_create_file(class_dev, - &class_device_attr_loading); - if (retval){ - printk(KERN_ERR "%s: class_device_create_file failed\n", - __FUNCTION__); - goto error_remove_data; - } - - goto out; - -error_remove_data: - sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data); -error_unreg_class_dev: - class_device_unregister(class_dev); -error_free_fw_priv: - kfree(fw_priv); -out: - return retval; -} -static void fw_remove_class_device(struct class_device *class_dev) -{ - struct firmware_priv *fw_priv = class_get_devdata(class_dev); - - class_device_remove_file(class_dev, &class_device_attr_loading); - sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data); - class_device_unregister(class_dev); -} - -static struct class_device *class_dev; - -static struct device my_device = { - .bus_id = "my_dev0", -}; - -static int __init firmware_sample_init(void) -{ - int error; - - device_initialize(&my_device); - class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL); - if(!class_dev) - return -ENOMEM; - - error = fw_setup_class_device(class_dev, "my_firmware_image", - &my_device); - if(error){ - kfree(class_dev); - return error; - } - return 0; - -} -static void __exit firmware_sample_exit(void) -{ - struct firmware_priv *fw_priv = class_get_devdata(class_dev); - fw_remove_class_device(class_dev); - kfree(fw_priv); - kfree(class_dev); -} -module_init(firmware_sample_init); -module_exit(firmware_sample_exit); - diff --git a/samples/firmware_class/firmware_sample_driver.c b/samples/firmware_class/firmware_sample_driver.c new file mode 100644 index 000000000000..ff0f2f2bd1a8 --- /dev/null +++ b/samples/firmware_class/firmware_sample_driver.c @@ -0,0 +1,115 @@ +/* + * firmware_sample_driver.c - + * + * Copyright (c) 2003 Manuel Estrada Sainz + * + * Sample code on how to use request_firmware() from drivers. + * + */ + +#include +#include +#include +#include +#include + +#include "linux/firmware.h" + +static struct device ghost_device = { + .bus_id = "ghost0", +}; + + +static void sample_firmware_load(char *firmware, int size) +{ + u8 buf[size+1]; + memcpy(buf, firmware, size); + buf[size] = '\0'; + printk(KERN_INFO "firmware_sample_driver: firmware: %s\n", buf); +} + +static void sample_probe_default(void) +{ + /* uses the default method to get the firmware */ + const struct firmware *fw_entry; + printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n"); + + if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0) + { + printk(KERN_ERR + "firmware_sample_driver: Firmware not available\n"); + return; + } + + sample_firmware_load(fw_entry->data, fw_entry->size); + + release_firmware(fw_entry); + + /* finish setting up the device */ +} +static void sample_probe_specific(void) +{ + /* Uses some specific hotplug support to get the firmware from + * userspace directly into the hardware, or via some sysfs file */ + + /* NOTE: This currently doesn't work */ + + printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n"); + + if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0) + { + printk(KERN_ERR + "firmware_sample_driver: Firmware load failed\n"); + return; + } + + /* request_firmware blocks until userspace finished, so at + * this point the firmware should be already in the device */ + + /* finish setting up the device */ +} +static void sample_probe_async_cont(const struct firmware *fw, void *context) +{ + if(!fw){ + printk(KERN_ERR + "firmware_sample_driver: firmware load failed\n"); + return; + } + + printk(KERN_INFO "firmware_sample_driver: device pointer \"%s\"\n", + (char *)context); + sample_firmware_load(fw->data, fw->size); +} +static void sample_probe_async(void) +{ + /* Let's say that I can't sleep */ + int error; + error = request_firmware_nowait (THIS_MODULE, FW_ACTION_NOHOTPLUG, + "sample_driver_fw", &ghost_device, + "my device pointer", + sample_probe_async_cont); + if(error){ + printk(KERN_ERR + "firmware_sample_driver:" + " request_firmware_nowait failed\n"); + } +} + +static int sample_init(void) +{ + device_initialize(&ghost_device); + /* since there is no real hardware insertion I just call the + * sample probe functions here */ + sample_probe_specific(); + sample_probe_default(); + sample_probe_async(); + return 0; +} +static void __exit sample_exit(void) +{ +} + +module_init (sample_init); +module_exit (sample_exit); + +MODULE_LICENSE("GPL"); diff --git a/samples/firmware_class/firmware_sample_firmware_class.c b/samples/firmware_class/firmware_sample_firmware_class.c new file mode 100644 index 000000000000..2799c472133e --- /dev/null +++ b/samples/firmware_class/firmware_sample_firmware_class.c @@ -0,0 +1,207 @@ +/* + * firmware_sample_firmware_class.c - + * + * Copyright (c) 2003 Manuel Estrada Sainz + * + * NOTE: This is just a probe of concept, if you think that your driver would + * be well served by this mechanism please contact me first. + * + * DON'T USE THIS CODE AS IS + * + */ + +#include +#include +#include +#include +#include +#include +#include + + +MODULE_AUTHOR("Manuel Estrada Sainz"); +MODULE_DESCRIPTION("Hackish sample for using firmware class directly"); +MODULE_LICENSE("GPL"); + +static inline struct class_device *to_class_dev(struct kobject *obj) +{ + return container_of(obj,struct class_device,kobj); +} +static inline +struct class_device_attribute *to_class_dev_attr(struct attribute *_attr) +{ + return container_of(_attr,struct class_device_attribute,attr); +} + +int sysfs_create_bin_file(struct kobject * kobj, struct bin_attribute * attr); +int sysfs_remove_bin_file(struct kobject * kobj, struct bin_attribute * attr); + +struct firmware_priv { + char fw_id[FIRMWARE_NAME_MAX]; + s32 loading:2; + u32 abort:1; +}; + +extern struct class firmware_class; + +static ssize_t firmware_loading_show(struct class_device *class_dev, char *buf) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + return sprintf(buf, "%d\n", fw_priv->loading); +} +static ssize_t firmware_loading_store(struct class_device *class_dev, + const char *buf, size_t count) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + int prev_loading = fw_priv->loading; + + fw_priv->loading = simple_strtol(buf, NULL, 10); + + switch(fw_priv->loading){ + case -1: + /* abort load an panic */ + break; + case 1: + /* setup load */ + break; + case 0: + if(prev_loading==1){ + /* finish load and get the device back to working + * state */ + } + break; + } + + return count; +} +static CLASS_DEVICE_ATTR(loading, 0644, + firmware_loading_show, firmware_loading_store); + +static ssize_t firmware_data_read(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t offset, size_t count) +{ + struct class_device *class_dev = to_class_dev(kobj); + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + + /* read from the devices firmware memory */ + + return count; +} +static ssize_t firmware_data_write(struct kobject *kobj, + struct bin_attribute *bin_attr, + char *buffer, loff_t offset, size_t count) +{ + struct class_device *class_dev = to_class_dev(kobj); + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + + /* write to the devices firmware memory */ + + return count; +} +static struct bin_attribute firmware_attr_data = { + .attr = {.name = "data", .mode = 0644}, + .size = 0, + .read = firmware_data_read, + .write = firmware_data_write, +}; +static int fw_setup_class_device(struct class_device *class_dev, + const char *fw_name, + struct device *device) +{ + int retval; + struct firmware_priv *fw_priv; + + fw_priv = kzalloc(sizeof(struct firmware_priv), GFP_KERNEL); + if (!fw_priv) { + retval = -ENOMEM; + goto out; + } + + memset(class_dev, 0, sizeof(*class_dev)); + + strncpy(fw_priv->fw_id, fw_name, FIRMWARE_NAME_MAX); + fw_priv->fw_id[FIRMWARE_NAME_MAX-1] = '\0'; + + strncpy(class_dev->class_id, device->bus_id, BUS_ID_SIZE); + class_dev->class_id[BUS_ID_SIZE-1] = '\0'; + class_dev->dev = device; + + class_dev->class = &firmware_class, + class_set_devdata(class_dev, fw_priv); + retval = class_device_register(class_dev); + if (retval){ + printk(KERN_ERR "%s: class_device_register failed\n", + __FUNCTION__); + goto error_free_fw_priv; + } + + retval = sysfs_create_bin_file(&class_dev->kobj, &firmware_attr_data); + if (retval){ + printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", + __FUNCTION__); + goto error_unreg_class_dev; + } + + retval = class_device_create_file(class_dev, + &class_device_attr_loading); + if (retval){ + printk(KERN_ERR "%s: class_device_create_file failed\n", + __FUNCTION__); + goto error_remove_data; + } + + goto out; + +error_remove_data: + sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data); +error_unreg_class_dev: + class_device_unregister(class_dev); +error_free_fw_priv: + kfree(fw_priv); +out: + return retval; +} +static void fw_remove_class_device(struct class_device *class_dev) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + + class_device_remove_file(class_dev, &class_device_attr_loading); + sysfs_remove_bin_file(&class_dev->kobj, &firmware_attr_data); + class_device_unregister(class_dev); +} + +static struct class_device *class_dev; + +static struct device my_device = { + .bus_id = "my_dev0", +}; + +static int __init firmware_sample_init(void) +{ + int error; + + device_initialize(&my_device); + class_dev = kmalloc(sizeof(struct class_device), GFP_KERNEL); + if(!class_dev) + return -ENOMEM; + + error = fw_setup_class_device(class_dev, "my_firmware_image", + &my_device); + if(error){ + kfree(class_dev); + return error; + } + return 0; + +} +static void __exit firmware_sample_exit(void) +{ + struct firmware_priv *fw_priv = class_get_devdata(class_dev); + fw_remove_class_device(class_dev); + kfree(fw_priv); + kfree(class_dev); +} + +module_init(firmware_sample_init); +module_exit(firmware_sample_exit); -- cgit v1.2.3 From 58aca23226a19983571bd3b65167521fc64f5869 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Wed, 12 Mar 2008 00:57:22 +0100 Subject: PM: Handle device registrations during suspend/resume Modify the PM core to protect its data structures, specifically the dpm_active list, from being corrupted if a child of the currently suspending device is registered concurrently with its ->suspend() callback. In that case, since the new device (the child) is added to dpm_active after its parent, the PM core will attempt to suspend it after the parent, which is wrong. Introduce a new member of struct dev_pm_info, called 'sleeping', and use it to check if the parent of the device being added to dpm_active has been suspended, in which case the device registration fails. Also, use 'sleeping' for checking if the ordering of devices on dpm_active is correct. Introduce variable 'all_sleeping' that will be set to 'true' once all devices have been suspended and make new device registrations fail until 'all_sleeping' is reset to 'false', in order to avoid having unsuspended devices around while the system is going into a sleep state. Remove pm_sleep_rwsem which is not necessary any more. Special thanks to Alan Stern for discussions and suggestions that lead to the creation of this patch. Signed-off-by: Rafael J. Wysocki Acked-by: Pavel Machek Signed-off-by: Greg Kroah-Hartman --- Documentation/power/devices.txt | 5 ++++ drivers/base/core.c | 6 ++++- drivers/base/power/main.c | 57 +++++++++++++++++++---------------------- drivers/base/power/power.h | 23 +++-------------- include/linux/pm.h | 1 + 5 files changed, 40 insertions(+), 52 deletions(-) (limited to 'Documentation') diff --git a/Documentation/power/devices.txt b/Documentation/power/devices.txt index 461e4f1dbec4..421e7d00ffd0 100644 --- a/Documentation/power/devices.txt +++ b/Documentation/power/devices.txt @@ -196,6 +196,11 @@ its parent; and can't be removed or suspended after that parent. The policy is that the device tree should match hardware bus topology. (Or at least the control bus, for devices which use multiple busses.) +In particular, this means that a device registration may fail if the parent of +the device is suspending (ie. has been chosen by the PM core as the next +device to suspend) or has already suspended, as well as after all of the other +devices have been suspended. Device drivers must be prepared to cope with such +situations. Suspending Devices diff --git a/drivers/base/core.c b/drivers/base/core.c index 24198ad01976..79848e6c5db5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -820,7 +820,11 @@ int device_add(struct device *dev) error = dpm_sysfs_add(dev); if (error) goto PMError; - device_pm_add(dev); + error = device_pm_add(dev); + if (error) { + dpm_sysfs_remove(dev); + goto PMError; + } error = bus_add_device(dev); if (error) goto BusError; diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 26de2c0fda80..0e3991a437c6 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -54,7 +54,8 @@ static LIST_HEAD(dpm_destroy); static DEFINE_MUTEX(dpm_list_mtx); -static DECLARE_RWSEM(pm_sleep_rwsem); +/* 'true' if all devices have been suspended, protected by dpm_list_mtx */ +static bool all_sleeping; int (*platform_enable_wakeup)(struct device *dev, int is_on); @@ -62,14 +63,28 @@ int (*platform_enable_wakeup)(struct device *dev, int is_on); * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list */ -void device_pm_add(struct device *dev) +int device_pm_add(struct device *dev) { + int error = 0; + pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); - list_add_tail(&dev->power.entry, &dpm_active); + if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) { + if (dev->parent->power.sleeping) + dev_warn(dev, + "parent %s is sleeping, will not add\n", + dev->parent->bus_id); + else + dev_warn(dev, "devices are sleeping, will not add\n"); + WARN_ON(true); + error = -EBUSY; + } else { + list_add_tail(&dev->power.entry, &dpm_active); + } mutex_unlock(&dpm_list_mtx); + return error; } /** @@ -107,32 +122,6 @@ void device_pm_schedule_removal(struct device *dev) } EXPORT_SYMBOL_GPL(device_pm_schedule_removal); -/** - * pm_sleep_lock - mutual exclusion for registration and suspend - * - * Returns 0 if no suspend is underway and device registration - * may proceed, otherwise -EBUSY. - */ -int pm_sleep_lock(void) -{ - if (down_read_trylock(&pm_sleep_rwsem)) - return 0; - - return -EBUSY; -} - -/** - * pm_sleep_unlock - mutual exclusion for registration and suspend - * - * This routine undoes the effect of device_pm_add_lock - * when a device's registration is complete. - */ -void pm_sleep_unlock(void) -{ - up_read(&pm_sleep_rwsem); -} - - /*------------------------- Resume routines -------------------------*/ /** @@ -242,11 +231,13 @@ static int resume_device(struct device *dev) static void dpm_resume(void) { mutex_lock(&dpm_list_mtx); + all_sleeping = false; while(!list_empty(&dpm_off)) { struct list_head *entry = dpm_off.next; struct device *dev = to_device(entry); list_move_tail(entry, &dpm_active); + dev->power.sleeping = false; mutex_unlock(&dpm_list_mtx); resume_device(dev); mutex_lock(&dpm_list_mtx); @@ -285,7 +276,6 @@ void device_resume(void) might_sleep(); dpm_resume(); unregister_dropped_devices(); - up_write(&pm_sleep_rwsem); } EXPORT_SYMBOL_GPL(device_resume); @@ -421,6 +411,9 @@ static int dpm_suspend(pm_message_t state) struct list_head *entry = dpm_active.prev; struct device *dev = to_device(entry); + WARN_ON(dev->parent && dev->parent->power.sleeping); + + dev->power.sleeping = true; mutex_unlock(&dpm_list_mtx); error = suspend_device(dev, state); mutex_lock(&dpm_list_mtx); @@ -432,11 +425,14 @@ static int dpm_suspend(pm_message_t state) (error == -EAGAIN ? " (please convert to suspend_late)" : "")); + dev->power.sleeping = false; break; } if (!list_empty(&dev->power.entry)) list_move(&dev->power.entry, &dpm_off); } + if (!error) + all_sleeping = true; mutex_unlock(&dpm_list_mtx); return error; @@ -454,7 +450,6 @@ int device_suspend(pm_message_t state) int error; might_sleep(); - down_write(&pm_sleep_rwsem); error = dpm_suspend(state); if (error) device_resume(); diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index e32d3bdb92c1..a6894f2a4b99 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -11,30 +11,13 @@ static inline struct device *to_device(struct list_head *entry) return container_of(entry, struct device, power.entry); } -extern void device_pm_add(struct device *); +extern int device_pm_add(struct device *); extern void device_pm_remove(struct device *); -extern int pm_sleep_lock(void); -extern void pm_sleep_unlock(void); #else /* CONFIG_PM_SLEEP */ - -static inline void device_pm_add(struct device *dev) -{ -} - -static inline void device_pm_remove(struct device *dev) -{ -} - -static inline int pm_sleep_lock(void) -{ - return 0; -} - -static inline void pm_sleep_unlock(void) -{ -} +static inline int device_pm_add(struct device *dev) { return 0; } +static inline void device_pm_remove(struct device *dev) {} #endif diff --git a/include/linux/pm.h b/include/linux/pm.h index 015b735811b4..e6b9f29e27d7 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -183,6 +183,7 @@ typedef struct pm_message { struct dev_pm_info { pm_message_t power_state; unsigned can_wakeup:1; + bool sleeping:1; /* Owned by the PM core */ #ifdef CONFIG_PM_SLEEP unsigned should_wakeup:1; struct list_head entry; -- cgit v1.2.3 From 95bc6a10830de469eee94c17fb1c37b3b1430715 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 28 Mar 2008 14:22:52 -0700 Subject: PM: Remove legacy PM (fix) Source file was removed. Need to remove docbook reference also. Signed-off-by: Randy Dunlap Cc: Pavel Machek Cc: Rafael J. Wysocki Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/DocBook/kernel-api.tmpl | 5 ----- 1 file changed, 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index dc0f30c3e571..488dd4a4945b 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -297,11 +297,6 @@ X!Earch/x86/kernel/mca_32.c !Ikernel/acct.c - - Power Management -!Ekernel/power/pm.c - - Device drivers infrastructure Device Drivers Base -- cgit v1.2.3 From 138fe4e069798d9aa948a5402ff15e58f483ee4e Mon Sep 17 00:00:00 2001 From: Konrad Rzeszutek Date: Wed, 9 Apr 2008 19:50:41 -0700 Subject: Firmware: add iSCSI iBFT Support Add /sysfs/firmware/ibft/[initiator|targetX|ethernetX] directories along with text properties which export the the iSCSI Boot Firmware Table (iBFT) structure. What is iSCSI Boot Firmware Table? It is a mechanism for the iSCSI tools to extract from the machine NICs the iSCSI connection information so that they can automagically mount the iSCSI share/target. Currently the iSCSI information is hard-coded in the initrd. The /sysfs entries are read-only one-name-and-value fields. The usual set of data exposed is: # for a in `find /sys/firmware/ibft/ -type f -print`; do echo -n "$a: "; cat $a; done /sys/firmware/ibft/target0/target-name: iqn.2007.com.intel-sbx44:storage-10gb /sys/firmware/ibft/target0/nic-assoc: 0 /sys/firmware/ibft/target0/chap-type: 0 /sys/firmware/ibft/target0/lun: 00000000 /sys/firmware/ibft/target0/port: 3260 /sys/firmware/ibft/target0/ip-addr: 192.168.79.116 /sys/firmware/ibft/target0/flags: 3 /sys/firmware/ibft/target0/index: 0 /sys/firmware/ibft/ethernet0/mac: 00:11:25:9d:8b:01 /sys/firmware/ibft/ethernet0/vlan: 0 /sys/firmware/ibft/ethernet0/gateway: 192.168.79.254 /sys/firmware/ibft/ethernet0/origin: 0 /sys/firmware/ibft/ethernet0/subnet-mask: 255.255.252.0 /sys/firmware/ibft/ethernet0/ip-addr: 192.168.77.41 /sys/firmware/ibft/ethernet0/flags: 7 /sys/firmware/ibft/ethernet0/index: 0 /sys/firmware/ibft/initiator/initiator-name: iqn.2007-07.com:konrad.initiator /sys/firmware/ibft/initiator/flags: 3 /sys/firmware/ibft/initiator/index: 0 For full details of the IBFT structure please take a look at: ftp://ftp.software.ibm.com/systems/support/system_x_pdf/ibm_iscsi_boot_firmware_table_v1.02.pdf [akpm@linux-foundation.org: fix build] Signed-off-by: Konrad Rzeszutek Cc: Mike Christie Cc: Peter Jones Cc: James Bottomley Cc: Ingo Molnar Cc: Thomas Gleixner Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-ibft | 23 + arch/x86/kernel/setup_32.c | 3 + arch/x86/kernel/setup_64.c | 4 + drivers/firmware/Kconfig | 20 + drivers/firmware/Makefile | 2 + drivers/firmware/iscsi_ibft.c | 982 +++++++++++++++++++++++++++++++++++ drivers/firmware/iscsi_ibft_find.c | 84 +++ include/linux/iscsi_ibft.h | 50 ++ 8 files changed, 1168 insertions(+) create mode 100644 Documentation/ABI/testing/sysfs-ibft create mode 100644 drivers/firmware/iscsi_ibft.c create mode 100644 drivers/firmware/iscsi_ibft_find.c create mode 100644 include/linux/iscsi_ibft.h (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-ibft b/Documentation/ABI/testing/sysfs-ibft new file mode 100644 index 000000000000..c2b7d1154bec --- /dev/null +++ b/Documentation/ABI/testing/sysfs-ibft @@ -0,0 +1,23 @@ +What: /sys/firmware/ibft/initiator +Date: November 2007 +Contact: Konrad Rzeszutek +Description: The /sys/firmware/ibft/initiator directory will contain + files that expose the iSCSI Boot Firmware Table initiator data. + Usually this contains the Initiator name. + +What: /sys/firmware/ibft/targetX +Date: November 2007 +Contact: Konrad Rzeszutek +Description: The /sys/firmware/ibft/targetX directory will contain + files that expose the iSCSI Boot Firmware Table target data. + Usually this contains the target's IP address, boot LUN, + target name, and what NIC it is associated with. It can also + contain the CHAP name (and password), the reverse CHAP + name (and password) + +What: /sys/firmware/ibft/ethernetX +Date: November 2007 +Contact: Konrad Rzeszutek +Description: The /sys/firmware/ibft/ethernetX directory will contain + files that expose the iSCSI Boot Firmware Table NIC data. + This can this can the IP address, MAC, and gateway of the NIC. diff --git a/arch/x86/kernel/setup_32.c b/arch/x86/kernel/setup_32.c index 5b0bffb7fcc9..4ef91749959e 100644 --- a/arch/x86/kernel/setup_32.c +++ b/arch/x86/kernel/setup_32.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -689,6 +690,8 @@ void __init setup_bootmem_allocator(void) #endif numa_kva_reserve(); reserve_crashkernel(); + + reserve_ibft_region(); } /* diff --git a/arch/x86/kernel/setup_64.c b/arch/x86/kernel/setup_64.c index 674ef3510cdf..216c93bd9993 100644 --- a/arch/x86/kernel/setup_64.c +++ b/arch/x86/kernel/setup_64.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -434,6 +435,9 @@ void __init setup_arch(char **cmdline_p) } #endif reserve_crashkernel(); + + reserve_ibft_region(); + paging_init(); map_vsyscall(); diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 05f02a326f1c..40ffd767647d 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -93,4 +93,24 @@ config DMIID information from userspace through /sys/class/dmi/id/ or if you want DMI-based module auto-loading. +config ISCSI_IBFT_FIND + bool "iSCSI Boot Firmware Table Attributes" + depends on X86 + default n + help + This option enables the kernel to find the region of memory + in which the ISCSI Boot Firmware Table (iBFT) resides. This + is necessary for iSCSI Boot Firmware Table Attributes module to work + properly. + +config ISCSI_IBFT + tristate "iSCSI Boot Firmware Table Attributes module" + depends on ISCSI_IBFT_FIND + default n + help + This option enables support for detection and exposing of iSCSI + Boot Firmware Table (iBFT) via sysfs to userspace. If you wish to + detect iSCSI boot parameters dynamically during system boot, say Y. + Otherwise, say N. + endmenu diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 8d4ebc805a50..4c9147154df8 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -8,3 +8,5 @@ obj-$(CONFIG_EFI_PCDP) += pcdp.o obj-$(CONFIG_DELL_RBU) += dell_rbu.o obj-$(CONFIG_DCDBAS) += dcdbas.o obj-$(CONFIG_DMIID) += dmi-id.o +obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o +obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o diff --git a/drivers/firmware/iscsi_ibft.c b/drivers/firmware/iscsi_ibft.c new file mode 100644 index 000000000000..8024e3bfd877 --- /dev/null +++ b/drivers/firmware/iscsi_ibft.c @@ -0,0 +1,982 @@ +/* + * Copyright 2007 Red Hat, Inc. + * by Peter Jones + * Copyright 2008 IBM, Inc. + * by Konrad Rzeszutek + * Copyright 2008 + * by Konrad Rzeszutek + * + * This code exposes the iSCSI Boot Format Table to userland via sysfs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2.0 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 General Public License for more details. + * + * Changelog: + * + * 14 Mar 2008 - Konrad Rzeszutek + * Updated comments and copyrights. (v0.4.9) + * + * 11 Feb 2008 - Konrad Rzeszutek + * Converted to using ibft_addr. (v0.4.8) + * + * 8 Feb 2008 - Konrad Rzeszutek + * Combined two functions in one: reserve_ibft_region. (v0.4.7) + * + * 30 Jan 2008 - Konrad Rzeszutek + * Added logic to handle IPv6 addresses. (v0.4.6) + * + * 25 Jan 2008 - Konrad Rzeszutek + * Added logic to handle badly not-to-spec iBFT. (v0.4.5) + * + * 4 Jan 2008 - Konrad Rzeszutek + * Added __init to function declarations. (v0.4.4) + * + * 21 Dec 2007 - Konrad Rzeszutek + * Updated kobject registration, combined unregister functions in one + * and code and style cleanup. (v0.4.3) + * + * 5 Dec 2007 - Konrad Rzeszutek + * Added end-markers to enums and re-organized kobject registration. (v0.4.2) + * + * 4 Dec 2007 - Konrad Rzeszutek + * Created 'device' sysfs link to the NIC and style cleanup. (v0.4.1) + * + * 28 Nov 2007 - Konrad Rzeszutek + * Added sysfs-ibft documentation, moved 'find_ibft' function to + * in its own file and added text attributes for every struct field. (v0.4) + * + * 21 Nov 2007 - Konrad Rzeszutek + * Added text attributes emulating OpenFirmware /proc/device-tree naming. + * Removed binary /sysfs interface (v0.3) + * + * 29 Aug 2007 - Konrad Rzeszutek + * Added functionality in setup.c to reserve iBFT region. (v0.2) + * + * 27 Aug 2007 - Konrad Rzeszutek + * First version exposing iBFT data via a binary /sysfs. (v0.1) + * + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define IBFT_ISCSI_VERSION "0.4.9" +#define IBFT_ISCSI_DATE "2008-Mar-14" + +MODULE_AUTHOR("Peter Jones and \ +Konrad Rzeszutek "); +MODULE_DESCRIPTION("sysfs interface to BIOS iBFT information"); +MODULE_LICENSE("GPL"); +MODULE_VERSION(IBFT_ISCSI_VERSION); + +struct ibft_hdr { + u8 id; + u8 version; + u16 length; + u8 index; + u8 flags; +} __attribute__((__packed__)); + +struct ibft_control { + struct ibft_hdr hdr; + u16 extensions; + u16 initiator_off; + u16 nic0_off; + u16 tgt0_off; + u16 nic1_off; + u16 tgt1_off; +} __attribute__((__packed__)); + +struct ibft_initiator { + struct ibft_hdr hdr; + char isns_server[16]; + char slp_server[16]; + char pri_radius_server[16]; + char sec_radius_server[16]; + u16 initiator_name_len; + u16 initiator_name_off; +} __attribute__((__packed__)); + +struct ibft_nic { + struct ibft_hdr hdr; + char ip_addr[16]; + u8 subnet_mask_prefix; + u8 origin; + char gateway[16]; + char primary_dns[16]; + char secondary_dns[16]; + char dhcp[16]; + u16 vlan; + char mac[6]; + u16 pci_bdf; + u16 hostname_len; + u16 hostname_off; +} __attribute__((__packed__)); + +struct ibft_tgt { + struct ibft_hdr hdr; + char ip_addr[16]; + u16 port; + char lun[8]; + u8 chap_type; + u8 nic_assoc; + u16 tgt_name_len; + u16 tgt_name_off; + u16 chap_name_len; + u16 chap_name_off; + u16 chap_secret_len; + u16 chap_secret_off; + u16 rev_chap_name_len; + u16 rev_chap_name_off; + u16 rev_chap_secret_len; + u16 rev_chap_secret_off; +} __attribute__((__packed__)); + +/* + * The kobject different types and its names. + * +*/ +enum ibft_id { + id_reserved = 0, /* We don't support. */ + id_control = 1, /* Should show up only once and is not exported. */ + id_initiator = 2, + id_nic = 3, + id_target = 4, + id_extensions = 5, /* We don't support. */ + id_end_marker, +}; + +/* + * We do not support the other types, hence the usage of NULL. + * This maps to the enum ibft_id. + */ +static const char *ibft_id_names[] = + {NULL, NULL, "initiator", "ethernet%d", "target%d", NULL, NULL}; + +/* + * The text attributes names for each of the kobjects. +*/ +enum ibft_eth_properties_enum { + ibft_eth_index, + ibft_eth_flags, + ibft_eth_ip_addr, + ibft_eth_subnet_mask, + ibft_eth_origin, + ibft_eth_gateway, + ibft_eth_primary_dns, + ibft_eth_secondary_dns, + ibft_eth_dhcp, + ibft_eth_vlan, + ibft_eth_mac, + /* ibft_eth_pci_bdf - this is replaced by link to the device itself. */ + ibft_eth_hostname, + ibft_eth_end_marker, +}; + +static const char *ibft_eth_properties[] = + {"index", "flags", "ip-addr", "subnet-mask", "origin", "gateway", + "primary-dns", "secondary-dns", "dhcp", "vlan", "mac", "hostname", + NULL}; + +enum ibft_tgt_properties_enum { + ibft_tgt_index, + ibft_tgt_flags, + ibft_tgt_ip_addr, + ibft_tgt_port, + ibft_tgt_lun, + ibft_tgt_chap_type, + ibft_tgt_nic_assoc, + ibft_tgt_name, + ibft_tgt_chap_name, + ibft_tgt_chap_secret, + ibft_tgt_rev_chap_name, + ibft_tgt_rev_chap_secret, + ibft_tgt_end_marker, +}; + +static const char *ibft_tgt_properties[] = + {"index", "flags", "ip-addr", "port", "lun", "chap-type", "nic-assoc", + "target-name", "chap-name", "chap-secret", "rev-chap-name", + "rev-chap-name-secret", NULL}; + +enum ibft_initiator_properties_enum { + ibft_init_index, + ibft_init_flags, + ibft_init_isns_server, + ibft_init_slp_server, + ibft_init_pri_radius_server, + ibft_init_sec_radius_server, + ibft_init_initiator_name, + ibft_init_end_marker, +}; + +static const char *ibft_initiator_properties[] = + {"index", "flags", "isns-server", "slp-server", "pri-radius-server", + "sec-radius-server", "initiator-name", NULL}; + +/* + * The kobject and attribute structures. + */ + +struct ibft_kobject { + struct ibft_table_header *header; + union { + struct ibft_initiator *initiator; + struct ibft_nic *nic; + struct ibft_tgt *tgt; + struct ibft_hdr *hdr; + }; + struct kobject kobj; + struct list_head node; +}; + +struct ibft_attribute { + struct attribute attr; + ssize_t (*show) (struct ibft_kobject *entry, + struct ibft_attribute *attr, char *buf); + union { + struct ibft_initiator *initiator; + struct ibft_nic *nic; + struct ibft_tgt *tgt; + struct ibft_hdr *hdr; + }; + struct kobject *kobj; + int type; /* The enum of the type. This can be any value of: + ibft_eth_properties_enum, ibft_tgt_properties_enum, + or ibft_initiator_properties_enum. */ + struct list_head node; +}; + +static LIST_HEAD(ibft_attr_list); +static LIST_HEAD(ibft_kobject_list); + +static const char nulls[16]; + +/* + * Helper functions to parse data properly. + */ +static ssize_t sprintf_ipaddr(char *buf, u8 *ip) +{ + char *str = buf; + + if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] == 0 && + ip[4] == 0 && ip[5] == 0 && ip[6] == 0 && ip[7] == 0 && + ip[8] == 0 && ip[9] == 0 && ip[10] == 0xff && ip[11] == 0xff) { + /* + * IPV4 + */ + str += sprintf(buf, NIPQUAD_FMT, ip[12], + ip[13], ip[14], ip[15]); + } else { + /* + * IPv6 + */ + str += sprintf(str, NIP6_FMT, ntohs(ip[0]), ntohs(ip[1]), + ntohs(ip[2]), ntohs(ip[3]), ntohs(ip[4]), + ntohs(ip[5]), ntohs(ip[6]), ntohs(ip[7])); + } + str += sprintf(str, "\n"); + return str - buf; +} + +static ssize_t sprintf_string(char *str, int len, char *buf) +{ + return sprintf(str, "%.*s\n", len, buf); +} + +/* + * Helper function to verify the IBFT header. + */ +static int ibft_verify_hdr(char *t, struct ibft_hdr *hdr, int id, int length) +{ + if (hdr->id != id) { + printk(KERN_ERR "iBFT error: We expected the " \ + "field header.id to have %d but " \ + "found %d instead!\n", id, hdr->id); + return -ENODEV; + } + if (hdr->length != length) { + printk(KERN_ERR "iBFT error: We expected the " \ + "field header.length to have %d but " \ + "found %d instead!\n", length, hdr->length); + return -ENODEV; + } + + return 0; +} + +static void ibft_release(struct kobject *kobj) +{ + struct ibft_kobject *ibft = + container_of(kobj, struct ibft_kobject, kobj); + kfree(ibft); +} + +/* + * Routines for parsing the iBFT data to be human readable. + */ +ssize_t ibft_attr_show_initiator(struct ibft_kobject *entry, + struct ibft_attribute *attr, + char *buf) +{ + struct ibft_initiator *initiator = entry->initiator; + void *ibft_loc = entry->header; + char *str = buf; + + if (!initiator) + return 0; + + switch (attr->type) { + case ibft_init_index: + str += sprintf(str, "%d\n", initiator->hdr.index); + break; + case ibft_init_flags: + str += sprintf(str, "%d\n", initiator->hdr.flags); + break; + case ibft_init_isns_server: + str += sprintf_ipaddr(str, initiator->isns_server); + break; + case ibft_init_slp_server: + str += sprintf_ipaddr(str, initiator->slp_server); + break; + case ibft_init_pri_radius_server: + str += sprintf_ipaddr(str, initiator->pri_radius_server); + break; + case ibft_init_sec_radius_server: + str += sprintf_ipaddr(str, initiator->sec_radius_server); + break; + case ibft_init_initiator_name: + str += sprintf_string(str, initiator->initiator_name_len, + (char *)ibft_loc + + initiator->initiator_name_off); + break; + default: + break; + } + + return str - buf; +} + +ssize_t ibft_attr_show_nic(struct ibft_kobject *entry, + struct ibft_attribute *attr, + char *buf) +{ + struct ibft_nic *nic = entry->nic; + void *ibft_loc = entry->header; + char *str = buf; + char *mac; + int val; + + if (!nic) + return 0; + + switch (attr->type) { + case ibft_eth_index: + str += sprintf(str, "%d\n", nic->hdr.index); + break; + case ibft_eth_flags: + str += sprintf(str, "%d\n", nic->hdr.flags); + break; + case ibft_eth_ip_addr: + str += sprintf_ipaddr(str, nic->ip_addr); + break; + case ibft_eth_subnet_mask: + val = ~((1 << (32-nic->subnet_mask_prefix))-1); + str += sprintf(str, NIPQUAD_FMT, + (u8)(val >> 24), (u8)(val >> 16), + (u8)(val >> 8), (u8)(val)); + break; + case ibft_eth_origin: + str += sprintf(str, "%d\n", nic->origin); + break; + case ibft_eth_gateway: + str += sprintf_ipaddr(str, nic->gateway); + break; + case ibft_eth_primary_dns: + str += sprintf_ipaddr(str, nic->primary_dns); + break; + case ibft_eth_secondary_dns: + str += sprintf_ipaddr(str, nic->secondary_dns); + break; + case ibft_eth_dhcp: + str += sprintf_ipaddr(str, nic->dhcp); + break; + case ibft_eth_vlan: + str += sprintf(str, "%d\n", nic->vlan); + break; + case ibft_eth_mac: + mac = nic->mac; + str += sprintf(str, "%02x:%02x:%02x:%02x:%02x:%02x\n", + (u8)mac[0], (u8)mac[1], (u8)mac[2], + (u8)mac[3], (u8)mac[4], (u8)mac[5]); + break; + case ibft_eth_hostname: + str += sprintf_string(str, nic->hostname_len, + (char *)ibft_loc + nic->hostname_off); + break; + default: + break; + } + + return str - buf; +}; + +ssize_t ibft_attr_show_target(struct ibft_kobject *entry, + struct ibft_attribute *attr, + char *buf) +{ + struct ibft_tgt *tgt = entry->tgt; + void *ibft_loc = entry->header; + char *str = buf; + int i; + + if (!tgt) + return 0; + + switch (attr->type) { + case ibft_tgt_index: + str += sprintf(str, "%d\n", tgt->hdr.index); + break; + case ibft_tgt_flags: + str += sprintf(str, "%d\n", tgt->hdr.flags); + break; + case ibft_tgt_ip_addr: + str += sprintf_ipaddr(str, tgt->ip_addr); + break; + case ibft_tgt_port: + str += sprintf(str, "%d\n", tgt->port); + break; + case ibft_tgt_lun: + for (i = 0; i < 8; i++) + str += sprintf(str, "%x", (u8)tgt->lun[i]); + str += sprintf(str, "\n"); + break; + case ibft_tgt_nic_assoc: + str += sprintf(str, "%d\n", tgt->nic_assoc); + break; + case ibft_tgt_chap_type: + str += sprintf(str, "%d\n", tgt->chap_type); + break; + case ibft_tgt_name: + str += sprintf_string(str, tgt->tgt_name_len, + (char *)ibft_loc + tgt->tgt_name_off); + break; + case ibft_tgt_chap_name: + str += sprintf_string(str, tgt->chap_name_len, + (char *)ibft_loc + tgt->chap_name_off); + break; + case ibft_tgt_chap_secret: + str += sprintf_string(str, tgt->chap_secret_len, + (char *)ibft_loc + tgt->chap_secret_off); + break; + case ibft_tgt_rev_chap_name: + str += sprintf_string(str, tgt->rev_chap_name_len, + (char *)ibft_loc + + tgt->rev_chap_name_off); + break; + case ibft_tgt_rev_chap_secret: + str += sprintf_string(str, tgt->rev_chap_secret_len, + (char *)ibft_loc + + tgt->rev_chap_secret_off); + break; + default: + break; + } + + return str - buf; +} + +/* + * The routine called for all sysfs attributes. + */ +static ssize_t ibft_show_attribute(struct kobject *kobj, + struct attribute *attr, + char *buf) +{ + struct ibft_kobject *dev = + container_of(kobj, struct ibft_kobject, kobj); + struct ibft_attribute *ibft_attr = + container_of(attr, struct ibft_attribute, attr); + ssize_t ret = -EIO; + char *str = buf; + + if (!capable(CAP_SYS_ADMIN)) + return -EACCES; + + if (ibft_attr->show) + ret = ibft_attr->show(dev, ibft_attr, str); + + return ret; +} + +static struct sysfs_ops ibft_attr_ops = { + .show = ibft_show_attribute, +}; + +static struct kobj_type ibft_ktype = { + .release = ibft_release, + .sysfs_ops = &ibft_attr_ops, +}; + +static struct kset *ibft_kset; + +static int __init ibft_check_device(void) +{ + int len; + u8 *pos; + u8 csum = 0; + + len = ibft_addr->length; + + /* Sanity checking of iBFT. */ + if (ibft_addr->revision != 1) { + printk(KERN_ERR "iBFT module supports only revision 1, " \ + "while this is %d.\n", ibft_addr->revision); + return -ENOENT; + } + for (pos = (u8 *)ibft_addr; pos < (u8 *)ibft_addr + len; pos++) + csum += *pos; + + if (csum) { + printk(KERN_ERR "iBFT has incorrect checksum (0x%x)!\n", csum); + return -ENOENT; + } + + return 0; +} + +/* + * Helper function for ibft_register_kobjects. + */ +static int __init ibft_create_kobject(struct ibft_table_header *header, + struct ibft_hdr *hdr, + struct list_head *list) +{ + struct ibft_kobject *ibft_kobj = NULL; + struct ibft_nic *nic = (struct ibft_nic *)hdr; + struct pci_dev *pci_dev; + int rc = 0; + + ibft_kobj = kzalloc(sizeof(*ibft_kobj), GFP_KERNEL); + if (!ibft_kobj) + return -ENOMEM; + + ibft_kobj->header = header; + ibft_kobj->hdr = hdr; + + switch (hdr->id) { + case id_initiator: + rc = ibft_verify_hdr("initiator", hdr, id_initiator, + sizeof(*ibft_kobj->initiator)); + break; + case id_nic: + rc = ibft_verify_hdr("ethernet", hdr, id_nic, + sizeof(*ibft_kobj->nic)); + break; + case id_target: + rc = ibft_verify_hdr("target", hdr, id_target, + sizeof(*ibft_kobj->tgt)); + break; + case id_reserved: + case id_control: + case id_extensions: + /* Fields which we don't support. Ignore them */ + rc = 1; + break; + default: + printk(KERN_ERR "iBFT has unknown structure type (%d). " \ + "Report this bug to %.6s!\n", hdr->id, + header->oem_id); + rc = 1; + break; + } + + if (rc) { + /* Skip adding this kobject, but exit with non-fatal error. */ + kfree(ibft_kobj); + goto out_invalid_struct; + } + + ibft_kobj->kobj.kset = ibft_kset; + + rc = kobject_init_and_add(&ibft_kobj->kobj, &ibft_ktype, + NULL, ibft_id_names[hdr->id], hdr->index); + + if (rc) { + kfree(ibft_kobj); + goto out; + } + + kobject_uevent(&ibft_kobj->kobj, KOBJ_ADD); + + if (hdr->id == id_nic) { + /* + * We don't search for the device in other domains than + * zero. This is because on x86 platforms the BIOS + * executes only devices which are in domain 0. Furthermore, the + * iBFT spec doesn't have a domain id field :-( + */ + pci_dev = pci_get_bus_and_slot((nic->pci_bdf & 0xff00) >> 8, + (nic->pci_bdf & 0xff)); + if (pci_dev) { + rc = sysfs_create_link(&ibft_kobj->kobj, + &pci_dev->dev.kobj, "device"); + pci_dev_put(pci_dev); + } + } + + /* Nothing broke so lets add it to the list. */ + list_add_tail(&ibft_kobj->node, list); +out: + return rc; +out_invalid_struct: + /* Unsupported structs are skipped. */ + return 0; +} + +/* + * Scan the IBFT table structure for the NIC and Target fields. When + * found add them on the passed-in list. We do not support the other + * fields at this point, so they are skipped. + */ +static int __init ibft_register_kobjects(struct ibft_table_header *header, + struct list_head *list) +{ + struct ibft_control *control = NULL; + void *ptr, *end; + int rc = 0; + u16 offset; + u16 eot_offset; + + control = (void *)header + sizeof(*header); + end = (void *)control + control->hdr.length; + eot_offset = (void *)header + header->length - + (void *)control - sizeof(*header); + rc = ibft_verify_hdr("control", (struct ibft_hdr *)control, id_control, + sizeof(*control)); + + /* iBFT table safety checking */ + rc |= ((control->hdr.index) ? -ENODEV : 0); + if (rc) { + printk(KERN_ERR "iBFT error: Control header is invalid!\n"); + return rc; + } + for (ptr = &control->initiator_off; ptr < end; ptr += sizeof(u16)) { + offset = *(u16 *)ptr; + if (offset && offset < header->length && offset < eot_offset) { + rc = ibft_create_kobject(header, + (void *)header + offset, + list); + if (rc) + break; + } + } + + return rc; +} + +static void ibft_unregister(struct list_head *attr_list, + struct list_head *kobj_list) +{ + struct ibft_kobject *data = NULL, *n; + struct ibft_attribute *attr = NULL, *m; + + list_for_each_entry_safe(attr, m, attr_list, node) { + sysfs_remove_file(attr->kobj, &attr->attr); + list_del(&attr->node); + kfree(attr); + }; + list_del_init(attr_list); + + list_for_each_entry_safe(data, n, kobj_list, node) { + list_del(&data->node); + if (data->hdr->id == id_nic) + sysfs_remove_link(&data->kobj, "device"); + kobject_put(&data->kobj); + }; + list_del_init(kobj_list); +} + +static int __init ibft_create_attribute(struct ibft_kobject *kobj_data, + int type, + const char *name, + ssize_t (*show)(struct ibft_kobject *, + struct ibft_attribute*, + char *buf), + struct list_head *list) +{ + struct ibft_attribute *attr = NULL; + struct ibft_hdr *hdr = kobj_data->hdr; + + attr = kmalloc(sizeof(*attr), GFP_KERNEL); + if (!attr) + return -ENOMEM; + + attr->attr.name = name; + attr->attr.mode = S_IRUSR; + attr->attr.owner = THIS_MODULE; + + attr->hdr = hdr; + attr->show = show; + attr->kobj = &kobj_data->kobj; + attr->type = type; + + list_add_tail(&attr->node, list); + + return 0; +} + +/* + * Helper routiners to check to determine if the entry is valid + * in the proper iBFT structure. + */ +static int __init ibft_check_nic_for(struct ibft_nic *nic, int entry) +{ + int rc = 0; + + switch (entry) { + case ibft_eth_index: + case ibft_eth_flags: + rc = 1; + break; + case ibft_eth_ip_addr: + if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp))) + rc = 1; + break; + case ibft_eth_subnet_mask: + if (!memcmp(nic->dhcp, nulls, sizeof(nic->dhcp))) + rc = 1; + break; + case ibft_eth_origin: + rc = 1; + break; + case ibft_eth_gateway: + if (memcmp(nic->gateway, nulls, sizeof(nic->gateway))) + rc = 1; + break; + case ibft_eth_primary_dns: + if (memcmp(nic->primary_dns, nulls, + sizeof(nic->primary_dns))) + rc = 1; + break; + case ibft_eth_secondary_dns: + if (memcmp(nic->secondary_dns, nulls, + sizeof(nic->secondary_dns))) + rc = 1; + break; + case ibft_eth_dhcp: + if (memcmp(nic->dhcp, nulls, sizeof(nic->dhcp))) + rc = 1; + break; + case ibft_eth_vlan: + case ibft_eth_mac: + rc = 1; + break; + case ibft_eth_hostname: + if (nic->hostname_off) + rc = 1; + break; + default: + break; + } + + return rc; +} + +static int __init ibft_check_tgt_for(struct ibft_tgt *tgt, int entry) +{ + int rc = 0; + + switch (entry) { + case ibft_tgt_index: + case ibft_tgt_flags: + case ibft_tgt_ip_addr: + case ibft_tgt_port: + case ibft_tgt_lun: + case ibft_tgt_nic_assoc: + case ibft_tgt_chap_type: + rc = 1; + case ibft_tgt_name: + if (tgt->tgt_name_len) + rc = 1; + break; + case ibft_tgt_chap_name: + case ibft_tgt_chap_secret: + if (tgt->chap_name_len) + rc = 1; + break; + case ibft_tgt_rev_chap_name: + case ibft_tgt_rev_chap_secret: + if (tgt->rev_chap_name_len) + rc = 1; + break; + default: + break; + } + + return rc; +} + +static int __init ibft_check_initiator_for(struct ibft_initiator *init, + int entry) +{ + int rc = 0; + + switch (entry) { + case ibft_init_index: + case ibft_init_flags: + rc = 1; + break; + case ibft_init_isns_server: + if (memcmp(init->isns_server, nulls, + sizeof(init->isns_server))) + rc = 1; + break; + case ibft_init_slp_server: + if (memcmp(init->slp_server, nulls, + sizeof(init->slp_server))) + rc = 1; + break; + case ibft_init_pri_radius_server: + if (memcmp(init->pri_radius_server, nulls, + sizeof(init->pri_radius_server))) + rc = 1; + break; + case ibft_init_sec_radius_server: + if (memcmp(init->sec_radius_server, nulls, + sizeof(init->sec_radius_server))) + rc = 1; + break; + case ibft_init_initiator_name: + if (init->initiator_name_len) + rc = 1; + break; + default: + break; + } + + return rc; +} + +/* + * Register the attributes for all of the kobjects. + */ +static int __init ibft_register_attributes(struct list_head *kobject_list, + struct list_head *attr_list) +{ + int rc = 0, i = 0; + struct ibft_kobject *data = NULL; + struct ibft_attribute *attr = NULL, *m; + + list_for_each_entry(data, kobject_list, node) { + switch (data->hdr->id) { + case id_nic: + for (i = 0; i < ibft_eth_end_marker && !rc; i++) + if (ibft_check_nic_for(data->nic, i)) + rc = ibft_create_attribute(data, i, + ibft_eth_properties[i], + ibft_attr_show_nic, attr_list); + break; + case id_target: + for (i = 0; i < ibft_tgt_end_marker && !rc; i++) + if (ibft_check_tgt_for(data->tgt, i)) + rc = ibft_create_attribute(data, i, + ibft_tgt_properties[i], + ibft_attr_show_target, + attr_list); + break; + case id_initiator: + for (i = 0; i < ibft_init_end_marker && !rc; i++) + if (ibft_check_initiator_for( + data->initiator, i)) + rc = ibft_create_attribute(data, i, + ibft_initiator_properties[i], + ibft_attr_show_initiator, + attr_list); + break; + default: + break; + } + if (rc) + break; + } + list_for_each_entry_safe(attr, m, attr_list, node) { + rc = sysfs_create_file(attr->kobj, &attr->attr); + if (rc) { + list_del(&attr->node); + kfree(attr); + break; + } + } + + return rc; +} + +/* + * ibft_init() - creates sysfs tree entries for the iBFT data. + */ +static int __init ibft_init(void) +{ + int rc = 0; + + ibft_kset = kset_create_and_add("ibft", NULL, firmware_kobj); + if (!ibft_kset) + return -ENOMEM; + + if (ibft_addr) { + printk(KERN_INFO "iBFT detected at 0x%lx.\n", + virt_to_phys((void *)ibft_addr)); + + rc = ibft_check_device(); + if (rc) + goto out_firmware_unregister; + + /* Scan the IBFT for data and register the kobjects. */ + rc = ibft_register_kobjects(ibft_addr, &ibft_kobject_list); + if (rc) + goto out_free; + + /* Register the attributes */ + rc = ibft_register_attributes(&ibft_kobject_list, + &ibft_attr_list); + if (rc) + goto out_free; + } else + printk(KERN_INFO "No iBFT detected.\n"); + + return 0; + +out_free: + ibft_unregister(&ibft_attr_list, &ibft_kobject_list); +out_firmware_unregister: + kset_unregister(ibft_kset); + return rc; +} + +static void __exit ibft_exit(void) +{ + ibft_unregister(&ibft_attr_list, &ibft_kobject_list); + kset_unregister(ibft_kset); +} + +module_init(ibft_init); +module_exit(ibft_exit); diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c new file mode 100644 index 000000000000..d0e5fa4ea51b --- /dev/null +++ b/drivers/firmware/iscsi_ibft_find.c @@ -0,0 +1,84 @@ +/* + * Copyright 2007 Red Hat, Inc. + * by Peter Jones + * Copyright 2007 IBM, Inc. + * by Konrad Rzeszutek + * Copyright 2008 + * by Konrad Rzeszutek + * + * This code finds the iSCSI Boot Format Table. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2.0 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 General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* + * Physical location of iSCSI Boot Format Table. + */ +struct ibft_table_header *ibft_addr; +EXPORT_SYMBOL_GPL(ibft_addr); + +#define IBFT_SIGN "iBFT" +#define IBFT_SIGN_LEN 4 +#define IBFT_START 0x80000 /* 512kB */ +#define IBFT_END 0x100000 /* 1MB */ +#define VGA_MEM 0xA0000 /* VGA buffer */ +#define VGA_SIZE 0x20000 /* 128kB */ + + +/* + * Routine used to find the iSCSI Boot Format Table. The logical + * kernel address is set in the ibft_addr global variable. + */ +void __init reserve_ibft_region(void) +{ + unsigned long pos; + unsigned int len = 0; + void *virt; + + ibft_addr = 0; + + for (pos = IBFT_START; pos < IBFT_END; pos += 16) { + /* The table can't be inside the VGA BIOS reserved space, + * so skip that area */ + if (pos == VGA_MEM) + pos += VGA_SIZE; + virt = phys_to_virt(pos); + if (memcmp(virt, IBFT_SIGN, IBFT_SIGN_LEN) == 0) { + unsigned long *addr = + (unsigned long *)phys_to_virt(pos + 4); + len = *addr; + /* if the length of the table extends past 1M, + * the table cannot be valid. */ + if (pos + len <= (IBFT_END-1)) { + ibft_addr = (struct ibft_table_header *)virt; + break; + } + } + } + if (ibft_addr) + reserve_bootmem(pos, PAGE_ALIGN(len), BOOTMEM_DEFAULT); +} +EXPORT_SYMBOL_GPL(reserve_ibft_region); diff --git a/include/linux/iscsi_ibft.h b/include/linux/iscsi_ibft.h new file mode 100644 index 000000000000..6092487e2950 --- /dev/null +++ b/include/linux/iscsi_ibft.h @@ -0,0 +1,50 @@ +/* + * Copyright 2007 Red Hat, Inc. + * by Peter Jones + * Copyright 2007 IBM, Inc. + * by Konrad Rzeszutek + * Copyright 2008 + * by Konrad Rzeszutek + * + * This code exposes the iSCSI Boot Format Table to userland via sysfs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License v2.0 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 General Public License for more details. + */ + +#ifndef ISCSI_IBFT_H +#define ISCSI_IBFT_H + +struct ibft_table_header { + char signature[4]; + u32 length; + u8 revision; + u8 checksum; + char oem_id[6]; + char oem_table_id[8]; + char reserved[24]; +} __attribute__((__packed__)); + +/* + * Logical location of iSCSI Boot Format Table. + * If the value is NULL there is no iBFT on the machine. + */ +extern struct ibft_table_header *ibft_addr; + +/* + * Routine used to find and reserve the iSCSI Boot Format Table. The + * mapped address is set in the ibft_addr variable. + */ +#ifdef CONFIG_ISCSI_IBFT_FIND +extern void __init reserve_ibft_region(void); +#else +static inline void reserve_ibft_region(void) { } +#endif + +#endif /* ISCSI_IBFT_H */ -- cgit v1.2.3 From 2424b5dd062cbe3e0578ae7b11a1b360ad22f451 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Mon, 7 Apr 2008 15:35:01 -0700 Subject: sysfs: refill attribute buffer when reading from offset 0 Requiring userspace to close and re-open sysfs attributes has been the policy since before 2.6.12. It allows userspace to get a consistent snapshot of kernel state and consume it with incremental reads and seeks. Now, if the file position is zero the kernel assumes userspace wants to see the new value. The application for this change is to allow a userspace RAID metadata handler to check the state of an array without causing any memory allocations. Thus not causing writeback to a raid array that might be blocked waiting for userspace to take action. Cc: Neil Brown Acked-by: Tejun Heo Signed-off-by: Dan Williams Signed-off-by: Greg Kroah-Hartman --- Documentation/filesystems/sysfs.txt | 9 +++++++-- fs/sysfs/file.c | 5 ++--- 2 files changed, 9 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/sysfs.txt b/Documentation/filesystems/sysfs.txt index 4598ef7b622b..7f27b8f840d0 100644 --- a/Documentation/filesystems/sysfs.txt +++ b/Documentation/filesystems/sysfs.txt @@ -176,8 +176,10 @@ implementations: Recall that an attribute should only be exporting one value, or an array of similar values, so this shouldn't be that expensive. - This allows userspace to do partial reads and seeks arbitrarily over - the entire file at will. + This allows userspace to do partial reads and forward seeks + arbitrarily over the entire file at will. If userspace seeks back to + zero or does a pread(2) with an offset of '0' the show() method will + be called again, rearmed, to fill the buffer. - On write(2), sysfs expects the entire buffer to be passed during the first write. Sysfs then passes the entire buffer to the store() @@ -192,6 +194,9 @@ implementations: Other notes: +- Writing causes the show() method to be rearmed regardless of current + file position. + - The buffer will always be PAGE_SIZE bytes in length. On i386, this is 4096. diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c index a859c32ff93a..ade9a7e6a757 100644 --- a/fs/sysfs/file.c +++ b/fs/sysfs/file.c @@ -129,7 +129,7 @@ sysfs_read_file(struct file *file, char __user *buf, size_t count, loff_t *ppos) ssize_t retval = 0; mutex_lock(&buffer->mutex); - if (buffer->needs_read_fill) { + if (buffer->needs_read_fill || *ppos == 0) { retval = fill_read_buffer(file->f_path.dentry,buffer); if (retval) goto out; @@ -410,8 +410,7 @@ static int sysfs_release(struct inode *inode, struct file *filp) * return POLLERR|POLLPRI, and select will return the fd whether * it is waiting for read, write, or exceptions. * Once poll/select indicates that the value has changed, you - * need to close and re-open the file, as simply seeking and reading - * again will not get new data, or reset the state of 'poll'. + * need to close and re-open the file, or seek to 0 and read again. * Reminder: this only works for attributes which actively support * it, and it is not possible to test an attribute from userspace * to see if it supports poll (Neither 'poll' nor 'select' return -- cgit v1.2.3 From 4b5ff469234b8ab5cd05f4a201cbb229896729d0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 10 Mar 2008 17:16:32 -0700 Subject: PCI: doc/pci: create Documentation/PCI/ and move files into it Create Documentation/PCI/ and move PCI-related files to it. Fix a few instances of trailing whitespace. Update references to the new file locations. Signed-off-by: Randy Dunlap Cc: Jesse Barnes Signed-off-by: Greg Kroah-Hartman --- Documentation/00-INDEX | 10 - Documentation/PCI/00-INDEX | 12 + Documentation/PCI/PCIEBUS-HOWTO.txt | 217 +++++++++++ Documentation/PCI/pci-error-recovery.txt | 396 +++++++++++++++++++ Documentation/PCI/pci.txt | 646 +++++++++++++++++++++++++++++++ Documentation/PCI/pcieaer-howto.txt | 253 ++++++++++++ Documentation/PCIEBUS-HOWTO.txt | 217 ----------- Documentation/memory-barriers.txt | 4 +- Documentation/pci-error-recovery.txt | 396 ------------------- Documentation/pci.txt | 646 ------------------------------- Documentation/pcieaer-howto.txt | 253 ------------ 11 files changed, 1526 insertions(+), 1524 deletions(-) create mode 100644 Documentation/PCI/00-INDEX create mode 100644 Documentation/PCI/PCIEBUS-HOWTO.txt create mode 100644 Documentation/PCI/pci-error-recovery.txt create mode 100644 Documentation/PCI/pci.txt create mode 100644 Documentation/PCI/pcieaer-howto.txt delete mode 100644 Documentation/PCIEBUS-HOWTO.txt delete mode 100644 Documentation/pci-error-recovery.txt delete mode 100644 Documentation/pci.txt delete mode 100644 Documentation/pcieaer-howto.txt (limited to 'Documentation') diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index f7923a42e769..a82a113b4a4b 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -25,8 +25,6 @@ DMA-API.txt - DMA API, pci_ API & extensions for non-consistent memory machines. DMA-ISA-LPC.txt - How to do DMA with ISA (and LPC) devices. -DMA-mapping.txt - - info for PCI drivers using DMA portably across all platforms. DocBook/ - directory with DocBook templates etc. for kernel documentation. HOWTO @@ -43,8 +41,6 @@ ManagementStyle - how to (attempt to) manage kernel hackers. MSI-HOWTO.txt - the Message Signaled Interrupts (MSI) Driver Guide HOWTO and FAQ. -PCIEBUS-HOWTO.txt - - a guide describing the PCI Express Port Bus driver. RCU/ - directory with info on RCU (read-copy update). README.DAC960 @@ -285,12 +281,6 @@ parport.txt - how to use the parallel-port driver. parport-lowlevel.txt - description and usage of the low level parallel port functions. -pci-error-recovery.txt - - info on PCI error recovery. -pci.txt - - info on the PCI subsystem for device driver authors. -pcieaer-howto.txt - - the PCI Express Advanced Error Reporting Driver Guide HOWTO. pcmcia/ - info on the Linux PCMCIA driver. pi-futex.txt diff --git a/Documentation/PCI/00-INDEX b/Documentation/PCI/00-INDEX new file mode 100644 index 000000000000..49f43946c6b6 --- /dev/null +++ b/Documentation/PCI/00-INDEX @@ -0,0 +1,12 @@ +00-INDEX + - this file +PCI-DMA-mapping.txt + - info for PCI drivers using DMA portably across all platforms +PCIEBUS-HOWTO.txt + - a guide describing the PCI Express Port Bus driver +pci-error-recovery.txt + - info on PCI error recovery +pci.txt + - info on the PCI subsystem for device driver authors +pcieaer-howto.txt + - the PCI Express Advanced Error Reporting Driver Guide HOWTO diff --git a/Documentation/PCI/PCIEBUS-HOWTO.txt b/Documentation/PCI/PCIEBUS-HOWTO.txt new file mode 100644 index 000000000000..9a07e38631b0 --- /dev/null +++ b/Documentation/PCI/PCIEBUS-HOWTO.txt @@ -0,0 +1,217 @@ + The PCI Express Port Bus Driver Guide HOWTO + Tom L Nguyen tom.l.nguyen@intel.com + 11/03/2004 + +1. About this guide + +This guide describes the basics of the PCI Express Port Bus driver +and provides information on how to enable the service drivers to +register/unregister with the PCI Express Port Bus Driver. + +2. Copyright 2004 Intel Corporation + +3. What is the PCI Express Port Bus Driver + +A PCI Express Port is a logical PCI-PCI Bridge structure. There +are two types of PCI Express Port: the Root Port and the Switch +Port. The Root Port originates a PCI Express link from a PCI Express +Root Complex and the Switch Port connects PCI Express links to +internal logical PCI buses. The Switch Port, which has its secondary +bus representing the switch's internal routing logic, is called the +switch's Upstream Port. The switch's Downstream Port is bridging from +switch's internal routing bus to a bus representing the downstream +PCI Express link from the PCI Express Switch. + +A PCI Express Port can provide up to four distinct functions, +referred to in this document as services, depending on its port type. +PCI Express Port's services include native hotplug support (HP), +power management event support (PME), advanced error reporting +support (AER), and virtual channel support (VC). These services may +be handled by a single complex driver or be individually distributed +and handled by corresponding service drivers. + +4. Why use the PCI Express Port Bus Driver? + +In existing Linux kernels, the Linux Device Driver Model allows a +physical device to be handled by only a single driver. The PCI +Express Port is a PCI-PCI Bridge device with multiple distinct +services. To maintain a clean and simple solution each service +may have its own software service driver. In this case several +service drivers will compete for a single PCI-PCI Bridge device. +For example, if the PCI Express Root Port native hotplug service +driver is loaded first, it claims a PCI-PCI Bridge Root Port. The +kernel therefore does not load other service drivers for that Root +Port. In other words, it is impossible to have multiple service +drivers load and run on a PCI-PCI Bridge device simultaneously +using the current driver model. + +To enable multiple service drivers running simultaneously requires +having a PCI Express Port Bus driver, which manages all populated +PCI Express Ports and distributes all provided service requests +to the corresponding service drivers as required. Some key +advantages of using the PCI Express Port Bus driver are listed below: + + - Allow multiple service drivers to run simultaneously on + a PCI-PCI Bridge Port device. + + - Allow service drivers implemented in an independent + staged approach. + + - Allow one service driver to run on multiple PCI-PCI Bridge + Port devices. + + - Manage and distribute resources of a PCI-PCI Bridge Port + device to requested service drivers. + +5. Configuring the PCI Express Port Bus Driver vs. Service Drivers + +5.1 Including the PCI Express Port Bus Driver Support into the Kernel + +Including the PCI Express Port Bus driver depends on whether the PCI +Express support is included in the kernel config. The kernel will +automatically include the PCI Express Port Bus driver as a kernel +driver when the PCI Express support is enabled in the kernel. + +5.2 Enabling Service Driver Support + +PCI device drivers are implemented based on Linux Device Driver Model. +All service drivers are PCI device drivers. As discussed above, it is +impossible to load any service driver once the kernel has loaded the +PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver +Model requires some minimal changes on existing service drivers that +imposes no impact on the functionality of existing service drivers. + +A service driver is required to use the two APIs shown below to +register its service with the PCI Express Port Bus driver (see +section 5.2.1 & 5.2.2). It is important that a service driver +initializes the pcie_port_service_driver data structure, included in +header file /include/linux/pcieport_if.h, before calling these APIs. +Failure to do so will result an identity mismatch, which prevents +the PCI Express Port Bus driver from loading a service driver. + +5.2.1 pcie_port_service_register + +int pcie_port_service_register(struct pcie_port_service_driver *new) + +This API replaces the Linux Driver Model's pci_module_init API. A +service driver should always calls pcie_port_service_register at +module init. Note that after service driver being loaded, calls +such as pci_enable_device(dev) and pci_set_master(dev) are no longer +necessary since these calls are executed by the PCI Port Bus driver. + +5.2.2 pcie_port_service_unregister + +void pcie_port_service_unregister(struct pcie_port_service_driver *new) + +pcie_port_service_unregister replaces the Linux Driver Model's +pci_unregister_driver. It's always called by service driver when a +module exits. + +5.2.3 Sample Code + +Below is sample service driver code to initialize the port service +driver data structure. + +static struct pcie_port_service_id service_id[] = { { + .vendor = PCI_ANY_ID, + .device = PCI_ANY_ID, + .port_type = PCIE_RC_PORT, + .service_type = PCIE_PORT_SERVICE_AER, + }, { /* end: all zeroes */ } +}; + +static struct pcie_port_service_driver root_aerdrv = { + .name = (char *)device_name, + .id_table = &service_id[0], + + .probe = aerdrv_load, + .remove = aerdrv_unload, + + .suspend = aerdrv_suspend, + .resume = aerdrv_resume, +}; + +Below is a sample code for registering/unregistering a service +driver. + +static int __init aerdrv_service_init(void) +{ + int retval = 0; + + retval = pcie_port_service_register(&root_aerdrv); + if (!retval) { + /* + * FIX ME + */ + } + return retval; +} + +static void __exit aerdrv_service_exit(void) +{ + pcie_port_service_unregister(&root_aerdrv); +} + +module_init(aerdrv_service_init); +module_exit(aerdrv_service_exit); + +6. Possible Resource Conflicts + +Since all service drivers of a PCI-PCI Bridge Port device are +allowed to run simultaneously, below lists a few of possible resource +conflicts with proposed solutions. + +6.1 MSI Vector Resource + +The MSI capability structure enables a device software driver to call +pci_enable_msi to request MSI based interrupts. Once MSI interrupts +are enabled on a device, it stays in this mode until a device driver +calls pci_disable_msi to disable MSI interrupts and revert back to +INTx emulation mode. Since service drivers of the same PCI-PCI Bridge +port share the same physical device, if an individual service driver +calls pci_enable_msi/pci_disable_msi it may result unpredictable +behavior. For example, two service drivers run simultaneously on the +same physical Root Port. Both service drivers call pci_enable_msi to +request MSI based interrupts. A service driver may not know whether +any other service drivers have run on this Root Port. If either one +of them calls pci_disable_msi, it puts the other service driver +in a wrong interrupt mode. + +To avoid this situation all service drivers are not permitted to +switch interrupt mode on its device. The PCI Express Port Bus driver +is responsible for determining the interrupt mode and this should be +transparent to service drivers. Service drivers need to know only +the vector IRQ assigned to the field irq of struct pcie_device, which +is passed in when the PCI Express Port Bus driver probes each service +driver. Service drivers should use (struct pcie_device*)dev->irq to +call request_irq/free_irq. In addition, the interrupt mode is stored +in the field interrupt_mode of struct pcie_device. + +6.2 MSI-X Vector Resources + +Similar to the MSI a device driver for an MSI-X capable device can +call pci_enable_msix to request MSI-X interrupts. All service drivers +are not permitted to switch interrupt mode on its device. The PCI +Express Port Bus driver is responsible for determining the interrupt +mode and this should be transparent to service drivers. Any attempt +by service driver to call pci_enable_msix/pci_disable_msix may +result unpredictable behavior. Service drivers should use +(struct pcie_device*)dev->irq and call request_irq/free_irq. + +6.3 PCI Memory/IO Mapped Regions + +Service drivers for PCI Express Power Management (PME), Advanced +Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access +PCI configuration space on the PCI Express port. In all cases the +registers accessed are independent of each other. This patch assumes +that all service drivers will be well behaved and not overwrite +other service driver's configuration settings. + +6.4 PCI Config Registers + +Each service driver runs its PCI config operations on its own +capability structure except the PCI Express capability structure, in +which Root Control register and Device Control register are shared +between PME and AER. This patch assumes that all service drivers +will be well behaved and not overwrite other service driver's +configuration settings. diff --git a/Documentation/PCI/pci-error-recovery.txt b/Documentation/PCI/pci-error-recovery.txt new file mode 100644 index 000000000000..6650af432523 --- /dev/null +++ b/Documentation/PCI/pci-error-recovery.txt @@ -0,0 +1,396 @@ + + PCI Error Recovery + ------------------ + February 2, 2006 + + Current document maintainer: + Linas Vepstas + + +Many PCI bus controllers are able to detect a variety of hardware +PCI errors on the bus, such as parity errors on the data and address +busses, as well as SERR and PERR errors. Some of the more advanced +chipsets are able to deal with these errors; these include PCI-E chipsets, +and the PCI-host bridges found on IBM Power4 and Power5-based pSeries +boxes. A typical action taken is to disconnect the affected device, +halting all I/O to it. The goal of a disconnection is to avoid system +corruption; for example, to halt system memory corruption due to DMA's +to "wild" addresses. Typically, a reconnection mechanism is also +offered, so that the affected PCI device(s) are reset and put back +into working condition. The reset phase requires coordination +between the affected device drivers and the PCI controller chip. +This document describes a generic API for notifying device drivers +of a bus disconnection, and then performing error recovery. +This API is currently implemented in the 2.6.16 and later kernels. + +Reporting and recovery is performed in several steps. First, when +a PCI hardware error has resulted in a bus disconnect, that event +is reported as soon as possible to all affected device drivers, +including multiple instances of a device driver on multi-function +cards. This allows device drivers to avoid deadlocking in spinloops, +waiting for some i/o-space register to change, when it never will. +It also gives the drivers a chance to defer incoming I/O as +needed. + +Next, recovery is performed in several stages. Most of the complexity +is forced by the need to handle multi-function devices, that is, +devices that have multiple device drivers associated with them. +In the first stage, each driver is allowed to indicate what type +of reset it desires, the choices being a simple re-enabling of I/O +or requesting a hard reset (a full electrical #RST of the PCI card). +If any driver requests a full reset, that is what will be done. + +After a full reset and/or a re-enabling of I/O, all drivers are +again notified, so that they may then perform any device setup/config +that may be required. After these have all completed, a final +"resume normal operations" event is sent out. + +The biggest reason for choosing a kernel-based implementation rather +than a user-space implementation was the need to deal with bus +disconnects of PCI devices attached to storage media, and, in particular, +disconnects from devices holding the root file system. If the root +file system is disconnected, a user-space mechanism would have to go +through a large number of contortions to complete recovery. Almost all +of the current Linux file systems are not tolerant of disconnection +from/reconnection to their underlying block device. By contrast, +bus errors are easy to manage in the device driver. Indeed, most +device drivers already handle very similar recovery procedures; +for example, the SCSI-generic layer already provides significant +mechanisms for dealing with SCSI bus errors and SCSI bus resets. + + +Detailed Design +--------------- +Design and implementation details below, based on a chain of +public email discussions with Ben Herrenschmidt, circa 5 April 2005. + +The error recovery API support is exposed to the driver in the form of +a structure of function pointers pointed to by a new field in struct +pci_driver. A driver that fails to provide the structure is "non-aware", +and the actual recovery steps taken are platform dependent. The +arch/powerpc implementation will simulate a PCI hotplug remove/add. + +This structure has the form: +struct pci_error_handlers +{ + int (*error_detected)(struct pci_dev *dev, enum pci_channel_state); + int (*mmio_enabled)(struct pci_dev *dev); + int (*link_reset)(struct pci_dev *dev); + int (*slot_reset)(struct pci_dev *dev); + void (*resume)(struct pci_dev *dev); +}; + +The possible channel states are: +enum pci_channel_state { + pci_channel_io_normal, /* I/O channel is in normal state */ + pci_channel_io_frozen, /* I/O to channel is blocked */ + pci_channel_io_perm_failure, /* PCI card is dead */ +}; + +Possible return values are: +enum pci_ers_result { + PCI_ERS_RESULT_NONE, /* no result/none/not supported in device driver */ + PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */ + PCI_ERS_RESULT_NEED_RESET, /* Device driver wants slot to be reset. */ + PCI_ERS_RESULT_DISCONNECT, /* Device has completely failed, is unrecoverable */ + PCI_ERS_RESULT_RECOVERED, /* Device driver is fully recovered and operational */ +}; + +A driver does not have to implement all of these callbacks; however, +if it implements any, it must implement error_detected(). If a callback +is not implemented, the corresponding feature is considered unsupported. +For example, if mmio_enabled() and resume() aren't there, then it +is assumed that the driver is not doing any direct recovery and requires +a reset. If link_reset() is not implemented, the card is assumed as +not care about link resets. Typically a driver will want to know about +a slot_reset(). + +The actual steps taken by a platform to recover from a PCI error +event will be platform-dependent, but will follow the general +sequence described below. + +STEP 0: Error Event +------------------- +PCI bus error is detect by the PCI hardware. On powerpc, the slot +is isolated, in that all I/O is blocked: all reads return 0xffffffff, +all writes are ignored. + + +STEP 1: Notification +-------------------- +Platform calls the error_detected() callback on every instance of +every driver affected by the error. + +At this point, the device might not be accessible anymore, depending on +the platform (the slot will be isolated on powerpc). The driver may +already have "noticed" the error because of a failing I/O, but this +is the proper "synchronization point", that is, it gives the driver +a chance to cleanup, waiting for pending stuff (timers, whatever, etc...) +to complete; it can take semaphores, schedule, etc... everything but +touch the device. Within this function and after it returns, the driver +shouldn't do any new IOs. Called in task context. This is sort of a +"quiesce" point. See note about interrupts at the end of this doc. + +All drivers participating in this system must implement this call. +The driver must return one of the following result codes: + - PCI_ERS_RESULT_CAN_RECOVER: + Driver returns this if it thinks it might be able to recover + the HW by just banging IOs or if it wants to be given + a chance to extract some diagnostic information (see + mmio_enable, below). + - PCI_ERS_RESULT_NEED_RESET: + Driver returns this if it can't recover without a hard + slot reset. + - PCI_ERS_RESULT_DISCONNECT: + Driver returns this if it doesn't want to recover at all. + +The next step taken will depend on the result codes returned by the +drivers. + +If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER, +then the platform should re-enable IOs on the slot (or do nothing in +particular, if the platform doesn't isolate slots), and recovery +proceeds to STEP 2 (MMIO Enable). + +If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET), +then recovery proceeds to STEP 4 (Slot Reset). + +If the platform is unable to recover the slot, the next step +is STEP 6 (Permanent Failure). + +>>> The current powerpc implementation assumes that a device driver will +>>> *not* schedule or semaphore in this routine; the current powerpc +>>> implementation uses one kernel thread to notify all devices; +>>> thus, if one device sleeps/schedules, all devices are affected. +>>> Doing better requires complex multi-threaded logic in the error +>>> recovery implementation (e.g. waiting for all notification threads +>>> to "join" before proceeding with recovery.) This seems excessively +>>> complex and not worth implementing. + +>>> The current powerpc implementation doesn't much care if the device +>>> attempts I/O at this point, or not. I/O's will fail, returning +>>> a value of 0xff on read, and writes will be dropped. If the device +>>> driver attempts more than 10K I/O's to a frozen adapter, it will +>>> assume that the device driver has gone into an infinite loop, and +>>> it will panic the kernel. There doesn't seem to be any other +>>> way of stopping a device driver that insists on spinning on I/O. + +STEP 2: MMIO Enabled +------------------- +The platform re-enables MMIO to the device (but typically not the +DMA), and then calls the mmio_enabled() callback on all affected +device drivers. + +This is the "early recovery" call. IOs are allowed again, but DMA is +not (hrm... to be discussed, I prefer not), with some restrictions. This +is NOT a callback for the driver to start operations again, only to +peek/poke at the device, extract diagnostic information, if any, and +eventually do things like trigger a device local reset or some such, +but not restart operations. This is callback is made if all drivers on +a segment agree that they can try to recover and if no automatic link reset +was performed by the HW. If the platform can't just re-enable IOs without +a slot reset or a link reset, it wont call this callback, and instead +will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset) + +>>> The following is proposed; no platform implements this yet: +>>> Proposal: All I/O's should be done _synchronously_ from within +>>> this callback, errors triggered by them will be returned via +>>> the normal pci_check_whatever() API, no new error_detected() +>>> callback will be issued due to an error happening here. However, +>>> such an error might cause IOs to be re-blocked for the whole +>>> segment, and thus invalidate the recovery that other devices +>>> on the same segment might have done, forcing the whole segment +>>> into one of the next states, that is, link reset or slot reset. + +The driver should return one of the following result codes: + - PCI_ERS_RESULT_RECOVERED + Driver returns this if it thinks the device is fully + functional and thinks it is ready to start + normal driver operations again. There is no + guarantee that the driver will actually be + allowed to proceed, as another driver on the + same segment might have failed and thus triggered a + slot reset on platforms that support it. + + - PCI_ERS_RESULT_NEED_RESET + Driver returns this if it thinks the device is not + recoverable in it's current state and it needs a slot + reset to proceed. + + - PCI_ERS_RESULT_DISCONNECT + Same as above. Total failure, no recovery even after + reset driver dead. (To be defined more precisely) + +The next step taken depends on the results returned by the drivers. +If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform +proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations). + +If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform +proceeds to STEP 4 (Slot Reset) + +>>> The current powerpc implementation does not implement this callback. + + +STEP 3: Link Reset +------------------ +The platform resets the link, and then calls the link_reset() callback +on all affected device drivers. This is a PCI-Express specific state +and is done whenever a non-fatal error has been detected that can be +"solved" by resetting the link. This call informs the driver of the +reset and the driver should check to see if the device appears to be +in working condition. + +The driver is not supposed to restart normal driver I/O operations +at this point. It should limit itself to "probing" the device to +check it's recoverability status. If all is right, then the platform +will call resume() once all drivers have ack'd link_reset(). + + Result codes: + (identical to STEP 3 (MMIO Enabled) + +The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5 +(Resume Operations). + +>>> The current powerpc implementation does not implement this callback. + + +STEP 4: Slot Reset +------------------ +The platform performs a soft or hard reset of the device, and then +calls the slot_reset() callback. + +A soft reset consists of asserting the adapter #RST line and then +restoring the PCI BAR's and PCI configuration header to a state +that is equivalent to what it would be after a fresh system +power-on followed by power-on BIOS/system firmware initialization. +If the platform supports PCI hotplug, then the reset might be +performed by toggling the slot electrical power off/on. + +It is important for the platform to restore the PCI config space +to the "fresh poweron" state, rather than the "last state". After +a slot reset, the device driver will almost always use its standard +device initialization routines, and an unusual config space setup +may result in hung devices, kernel panics, or silent data corruption. + +This call gives drivers the chance to re-initialize the hardware +(re-download firmware, etc.). At this point, the driver may assume +that he card is in a fresh state and is fully functional. In +particular, interrupt generation should work normally. + +Drivers should not yet restart normal I/O processing operations +at this point. If all device drivers report success on this +callback, the platform will call resume() to complete the sequence, +and let the driver restart normal I/O processing. + +A driver can still return a critical failure for this function if +it can't get the device operational after reset. If the platform +previously tried a soft reset, it might now try a hard reset (power +cycle) and then call slot_reset() again. It the device still can't +be recovered, there is nothing more that can be done; the platform +will typically report a "permanent failure" in such a case. The +device will be considered "dead" in this case. + +Drivers for multi-function cards will need to coordinate among +themselves as to which driver instance will perform any "one-shot" +or global device initialization. For example, the Symbios sym53cxx2 +driver performs device init only from PCI function 0: + ++ if (PCI_FUNC(pdev->devfn) == 0) ++ sym_reset_scsi_bus(np, 0); + + Result codes: + - PCI_ERS_RESULT_DISCONNECT + Same as above. + +Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent +Failure). + +>>> The current powerpc implementation does not currently try a +>>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT. +>>> However, it probably should. + + +STEP 5: Resume Operations +------------------------- +The platform will call the resume() callback on all affected device +drivers if all drivers on the segment have returned +PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks. +The goal of this callback is to tell the driver to restart activity, +that everything is back and running. This callback does not return +a result code. + +At this point, if a new error happens, the platform will restart +a new error recovery sequence. + +STEP 6: Permanent Failure +------------------------- +A "permanent failure" has occurred, and the platform cannot recover +the device. The platform will call error_detected() with a +pci_channel_state value of pci_channel_io_perm_failure. + +The device driver should, at this point, assume the worst. It should +cancel all pending I/O, refuse all new I/O, returning -EIO to +higher layers. The device driver should then clean up all of its +memory and remove itself from kernel operations, much as it would +during system shutdown. + +The platform will typically notify the system operator of the +permanent failure in some way. If the device is hotplug-capable, +the operator will probably want to remove and replace the device. +Note, however, not all failures are truly "permanent". Some are +caused by over-heating, some by a poorly seated card. Many +PCI error events are caused by software bugs, e.g. DMA's to +wild addresses or bogus split transactions due to programming +errors. See the discussion in powerpc/eeh-pci-error-recovery.txt +for additional detail on real-life experience of the causes of +software errors. + + +Conclusion; General Remarks +--------------------------- +The way those callbacks are called is platform policy. A platform with +no slot reset capability may want to just "ignore" drivers that can't +recover (disconnect them) and try to let other cards on the same segment +recover. Keep in mind that in most real life cases, though, there will +be only one driver per segment. + +Now, a note about interrupts. If you get an interrupt and your +device is dead or has been isolated, there is a problem :) +The current policy is to turn this into a platform policy. +That is, the recovery API only requires that: + + - There is no guarantee that interrupt delivery can proceed from any +device on the segment starting from the error detection and until the +resume callback is sent, at which point interrupts are expected to be +fully operational. + + - There is no guarantee that interrupt delivery is stopped, that is, +a driver that gets an interrupt after detecting an error, or that detects +an error within the interrupt handler such that it prevents proper +ack'ing of the interrupt (and thus removal of the source) should just +return IRQ_NOTHANDLED. It's up to the platform to deal with that +condition, typically by masking the IRQ source during the duration of +the error handling. It is expected that the platform "knows" which +interrupts are routed to error-management capable slots and can deal +with temporarily disabling that IRQ number during error processing (this +isn't terribly complex). That means some IRQ latency for other devices +sharing the interrupt, but there is simply no other way. High end +platforms aren't supposed to share interrupts between many devices +anyway :) + +>>> Implementation details for the powerpc platform are discussed in +>>> the file Documentation/powerpc/eeh-pci-error-recovery.txt + +>>> As of this writing, there are six device drivers with patches +>>> implementing error recovery. Not all of these patches are in +>>> mainline yet. These may be used as "examples": +>>> +>>> drivers/scsi/ipr.c +>>> drivers/scsi/sym53cxx_2 +>>> drivers/next/e100.c +>>> drivers/net/e1000 +>>> drivers/net/ixgb +>>> drivers/net/s2io.c + +The End +------- diff --git a/Documentation/PCI/pci.txt b/Documentation/PCI/pci.txt new file mode 100644 index 000000000000..8d4dc6250c58 --- /dev/null +++ b/Documentation/PCI/pci.txt @@ -0,0 +1,646 @@ + + How To Write Linux PCI Drivers + + by Martin Mares on 07-Feb-2000 + updated by Grant Grundler on 23-Dec-2006 + +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The world of PCI is vast and full of (mostly unpleasant) surprises. +Since each CPU architecture implements different chip-sets and PCI devices +have different requirements (erm, "features"), the result is the PCI support +in the Linux kernel is not as trivial as one would wish. This short paper +tries to introduce all potential driver authors to Linux APIs for +PCI device drivers. + +A more complete resource is the third edition of "Linux Device Drivers" +by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman. +LDD3 is available for free (under Creative Commons License) from: + + http://lwn.net/Kernel/LDD3/ + +However, keep in mind that all documents are subject to "bit rot". +Refer to the source code if things are not working as described here. + +Please send questions/comments/patches about Linux PCI API to the +"Linux PCI" mailing list. + + + +0. Structure of PCI drivers +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +PCI drivers "discover" PCI devices in a system via pci_register_driver(). +Actually, it's the other way around. When the PCI generic code discovers +a new device, the driver with a matching "description" will be notified. +Details on this below. + +pci_register_driver() leaves most of the probing for devices to +the PCI layer and supports online insertion/removal of devices [thus +supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver]. +pci_register_driver() call requires passing in a table of function +pointers and thus dictates the high level structure of a driver. + +Once the driver knows about a PCI device and takes ownership, the +driver generally needs to perform the following initialization: + + Enable the device + Request MMIO/IOP resources + Set the DMA mask size (for both coherent and streaming DMA) + Allocate and initialize shared control data (pci_allocate_coherent()) + Access device configuration space (if needed) + Register IRQ handler (request_irq()) + Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip) + Enable DMA/processing engines + +When done using the device, and perhaps the module needs to be unloaded, +the driver needs to take the follow steps: + Disable the device from generating IRQs + Release the IRQ (free_irq()) + Stop all DMA activity + Release DMA buffers (both streaming and coherent) + Unregister from other subsystems (e.g. scsi or netdev) + Release MMIO/IOP resources + Disable the device + +Most of these topics are covered in the following sections. +For the rest look at LDD3 or . + +If the PCI subsystem is not configured (CONFIG_PCI is not set), most of +the PCI functions described below are defined as inline functions either +completely empty or just returning an appropriate error codes to avoid +lots of ifdefs in the drivers. + + + +1. pci_register_driver() call +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +PCI device drivers call pci_register_driver() during their +initialization with a pointer to a structure describing the driver +(struct pci_driver): + + field name Description + ---------- ------------------------------------------------------ + id_table Pointer to table of device ID's the driver is + interested in. Most drivers should export this + table using MODULE_DEVICE_TABLE(pci,...). + + probe This probing function gets called (during execution + of pci_register_driver() for already existing + devices or later if a new device gets inserted) for + all PCI devices which match the ID table and are not + "owned" by the other drivers yet. This function gets + passed a "struct pci_dev *" for each device whose + entry in the ID table matches the device. The probe + function returns zero when the driver chooses to + take "ownership" of the device or an error code + (negative number) otherwise. + The probe function always gets called from process + context, so it can sleep. + + remove The remove() function gets called whenever a device + being handled by this driver is removed (either during + deregistration of the driver or when it's manually + pulled out of a hot-pluggable slot). + The remove function always gets called from process + context, so it can sleep. + + suspend Put device into low power state. + suspend_late Put device into low power state. + + resume_early Wake device from low power state. + resume Wake device from low power state. + + (Please see Documentation/power/pci.txt for descriptions + of PCI Power Management and the related functions.) + + shutdown Hook into reboot_notifier_list (kernel/sys.c). + Intended to stop any idling DMA operations. + Useful for enabling wake-on-lan (NIC) or changing + the power state of a device before reboot. + e.g. drivers/net/e100.c. + + err_handler See Documentation/PCI/pci-error-recovery.txt + + +The ID table is an array of struct pci_device_id entries ending with an +all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred +method of declaring the table. Each entry consists of: + + vendor,device Vendor and device ID to match (or PCI_ANY_ID) + + subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID) + subdevice, + + class Device class, subclass, and "interface" to match. + See Appendix D of the PCI Local Bus Spec or + include/linux/pci_ids.h for a full list of classes. + Most drivers do not need to specify class/class_mask + as vendor/device is normally sufficient. + + class_mask limit which sub-fields of the class field are compared. + See drivers/scsi/sym53c8xx_2/ for example of usage. + + driver_data Data private to the driver. + Most drivers don't need to use driver_data field. + Best practice is to use driver_data as an index + into a static list of equivalent device types, + instead of using it as a pointer. + + +Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up +a pci_device_id table. + +New PCI IDs may be added to a device driver pci_ids table at runtime +as shown below: + +echo "vendor device subvendor subdevice class class_mask driver_data" > \ +/sys/bus/pci/drivers/{driver}/new_id + +All fields are passed in as hexadecimal values (no leading 0x). +The vendor and device fields are mandatory, the others are optional. Users +need pass only as many optional fields as necessary: + o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF) + o class and classmask fields default to 0 + o driver_data defaults to 0UL. + +Once added, the driver probe routine will be invoked for any unclaimed +PCI devices listed in its (newly updated) pci_ids list. + +When the driver exits, it just calls pci_unregister_driver() and the PCI layer +automatically calls the remove hook for all devices handled by the driver. + + +1.1 "Attributes" for driver functions/data + +Please mark the initialization and cleanup functions where appropriate +(the corresponding macros are defined in ): + + __init Initialization code. Thrown away after the driver + initializes. + __exit Exit code. Ignored for non-modular drivers. + + + __devinit Device initialization code. + Identical to __init if the kernel is not compiled + with CONFIG_HOTPLUG, normal function otherwise. + __devexit The same for __exit. + +Tips on when/where to use the above attributes: + o The module_init()/module_exit() functions (and all + initialization functions called _only_ from these) + should be marked __init/__exit. + + o Do not mark the struct pci_driver. + + o The ID table array should be marked __devinitconst; this is done + automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE(). + + o The probe() and remove() functions should be marked __devinit + and __devexit respectively. All initialization functions + exclusively called by the probe() routine, can be marked __devinit. + Ditto for remove() and __devexit. + + o If mydriver_remove() is marked with __devexit(), then all address + references to mydriver_remove must use __devexit_p(mydriver_remove) + (in the struct pci_driver declaration for example). + __devexit_p() will generate the function name _or_ NULL if the + function will be discarded. For an example, see drivers/net/tg3.c. + + o Do NOT mark a function if you are not sure which mark to use. + Better to not mark the function than mark the function wrong. + + + +2. How to find PCI devices manually +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +PCI drivers should have a really good reason for not using the +pci_register_driver() interface to search for PCI devices. +The main reason PCI devices are controlled by multiple drivers +is because one PCI device implements several different HW services. +E.g. combined serial/parallel port/floppy controller. + +A manual search may be performed using the following constructs: + +Searching by vendor and device ID: + + struct pci_dev *dev = NULL; + while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev)) + configure_device(dev); + +Searching by class ID (iterate in a similar way): + + pci_get_class(CLASS_ID, dev) + +Searching by both vendor/device and subsystem vendor/device ID: + + pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev). + +You can use the constant PCI_ANY_ID as a wildcard replacement for +VENDOR_ID or DEVICE_ID. This allows searching for any device from a +specific vendor, for example. + +These functions are hotplug-safe. They increment the reference count on +the pci_dev that they return. You must eventually (possibly at module unload) +decrement the reference count on these devices by calling pci_dev_put(). + + + +3. Device Initialization Steps +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As noted in the introduction, most PCI drivers need the following steps +for device initialization: + + Enable the device + Request MMIO/IOP resources + Set the DMA mask size (for both coherent and streaming DMA) + Allocate and initialize shared control data (pci_allocate_coherent()) + Access device configuration space (if needed) + Register IRQ handler (request_irq()) + Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip) + Enable DMA/processing engines. + +The driver can access PCI config space registers at any time. +(Well, almost. When running BIST, config space can go away...but +that will just result in a PCI Bus Master Abort and config reads +will return garbage). + + +3.1 Enable the PCI device +~~~~~~~~~~~~~~~~~~~~~~~~~ +Before touching any device registers, the driver needs to enable +the PCI device by calling pci_enable_device(). This will: + o wake up the device if it was in suspended state, + o allocate I/O and memory regions of the device (if BIOS did not), + o allocate an IRQ (if BIOS did not). + +NOTE: pci_enable_device() can fail! Check the return value. + +[ OS BUG: we don't check resource allocations before enabling those + resources. The sequence would make more sense if we called + pci_request_resources() before calling pci_enable_device(). + Currently, the device drivers can't detect the bug when when two + devices have been allocated the same range. This is not a common + problem and unlikely to get fixed soon. + + This has been discussed before but not changed as of 2.6.19: + http://lkml.org/lkml/2006/3/2/194 +] + +pci_set_master() will enable DMA by setting the bus master bit +in the PCI_COMMAND register. It also fixes the latency timer value if +it's set to something bogus by the BIOS. + +If the PCI device can use the PCI Memory-Write-Invalidate transaction, +call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval +and also ensures that the cache line size register is set correctly. +Check the return value of pci_set_mwi() as not all architectures +or chip-sets may support Memory-Write-Invalidate. Alternatively, +if Mem-Wr-Inval would be nice to have but is not required, call +pci_try_set_mwi() to have the system do its best effort at enabling +Mem-Wr-Inval. + + +3.2 Request MMIO/IOP resources +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Memory (MMIO), and I/O port addresses should NOT be read directly +from the PCI device config space. Use the values in the pci_dev structure +as the PCI "bus address" might have been remapped to a "host physical" +address by the arch/chip-set specific kernel support. + +See Documentation/IO-mapping.txt for how to access device registers +or device memory. + +The device driver needs to call pci_request_region() to verify +no other device is already using the same address resource. +Conversely, drivers should call pci_release_region() AFTER +calling pci_disable_device(). +The idea is to prevent two devices colliding on the same address range. + +[ See OS BUG comment above. Currently (2.6.19), The driver can only + determine MMIO and IO Port resource availability _after_ calling + pci_enable_device(). ] + +Generic flavors of pci_request_region() are request_mem_region() +(for MMIO ranges) and request_region() (for IO Port ranges). +Use these for address resources that are not described by "normal" PCI +BARs. + +Also see pci_request_selected_regions() below. + + +3.3 Set the DMA mask size +~~~~~~~~~~~~~~~~~~~~~~~~~ +[ If anything below doesn't make sense, please refer to + Documentation/DMA-API.txt. This section is just a reminder that + drivers need to indicate DMA capabilities of the device and is not + an authoritative source for DMA interfaces. ] + +While all drivers should explicitly indicate the DMA capability +(e.g. 32 or 64 bit) of the PCI bus master, devices with more than +32-bit bus master capability for streaming data need the driver +to "register" this capability by calling pci_set_dma_mask() with +appropriate parameters. In general this allows more efficient DMA +on systems where System RAM exists above 4G _physical_ address. + +Drivers for all PCI-X and PCIe compliant devices must call +pci_set_dma_mask() as they are 64-bit DMA devices. + +Similarly, drivers must also "register" this capability if the device +can directly address "consistent memory" in System RAM above 4G physical +address by calling pci_set_consistent_dma_mask(). +Again, this includes drivers for all PCI-X and PCIe compliant devices. +Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are +64-bit DMA capable for payload ("streaming") data but not control +("consistent") data. + + +3.4 Setup shared control data +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared) +memory. See Documentation/DMA-API.txt for a full description of +the DMA APIs. This section is just a reminder that it needs to be done +before enabling DMA on the device. + + +3.5 Initialize device registers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Some drivers will need specific "capability" fields programmed +or other "vendor specific" register initialized or reset. +E.g. clearing pending interrupts. + + +3.6 Register IRQ handler +~~~~~~~~~~~~~~~~~~~~~~~~ +While calling request_irq() is the last step described here, +this is often just another intermediate step to initialize a device. +This step can often be deferred until the device is opened for use. + +All interrupt handlers for IRQ lines should be registered with IRQF_SHARED +and use the devid to map IRQs to devices (remember that all PCI IRQ lines +can be shared). + +request_irq() will associate an interrupt handler and device handle +with an interrupt number. Historically interrupt numbers represent +IRQ lines which run from the PCI device to the Interrupt controller. +With MSI and MSI-X (more below) the interrupt number is a CPU "vector". + +request_irq() also enables the interrupt. Make sure the device is +quiesced and does not have any interrupts pending before registering +the interrupt handler. + +MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts" +which deliver interrupts to the CPU via a DMA write to a Local APIC. +The fundamental difference between MSI and MSI-X is how multiple +"vectors" get allocated. MSI requires contiguous blocks of vectors +while MSI-X can allocate several individual ones. + +MSI capability can be enabled by calling pci_enable_msi() or +pci_enable_msix() before calling request_irq(). This causes +the PCI support to program CPU vector data into the PCI device +capability registers. + +If your PCI device supports both, try to enable MSI-X first. +Only one can be enabled at a time. Many architectures, chip-sets, +or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix +will fail. This is important to note since many drivers have +two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs. +They choose which handler to register with request_irq() based on the +return value from pci_enable_msi/msix(). + +There are (at least) two really good reasons for using MSI: +1) MSI is an exclusive interrupt vector by definition. + This means the interrupt handler doesn't have to verify + its device caused the interrupt. + +2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed + to be visible to the host CPU(s) when the MSI is delivered. This + is important for both data coherency and avoiding stale control data. + This guarantee allows the driver to omit MMIO reads to flush + the DMA stream. + +See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples +of MSI/MSI-X usage. + + + +4. PCI device shutdown +~~~~~~~~~~~~~~~~~~~~~~~ + +When a PCI device driver is being unloaded, most of the following +steps need to be performed: + + Disable the device from generating IRQs + Release the IRQ (free_irq()) + Stop all DMA activity + Release DMA buffers (both streaming and consistent) + Unregister from other subsystems (e.g. scsi or netdev) + Disable device from responding to MMIO/IO Port addresses + Release MMIO/IO Port resource(s) + + +4.1 Stop IRQs on the device +~~~~~~~~~~~~~~~~~~~~~~~~~~~ +How to do this is chip/device specific. If it's not done, it opens +the possibility of a "screaming interrupt" if (and only if) +the IRQ is shared with another device. + +When the shared IRQ handler is "unhooked", the remaining devices +using the same IRQ line will still need the IRQ enabled. Thus if the +"unhooked" device asserts IRQ line, the system will respond assuming +it was one of the remaining devices asserted the IRQ line. Since none +of the other devices will handle the IRQ, the system will "hang" until +it decides the IRQ isn't going to get handled and masks the IRQ (100,000 +iterations later). Once the shared IRQ is masked, the remaining devices +will stop functioning properly. Not a nice situation. + +This is another reason to use MSI or MSI-X if it's available. +MSI and MSI-X are defined to be exclusive interrupts and thus +are not susceptible to the "screaming interrupt" problem. + + +4.2 Release the IRQ +~~~~~~~~~~~~~~~~~~~ +Once the device is quiesced (no more IRQs), one can call free_irq(). +This function will return control once any pending IRQs are handled, +"unhook" the drivers IRQ handler from that IRQ, and finally release +the IRQ if no one else is using it. + + +4.3 Stop all DMA activity +~~~~~~~~~~~~~~~~~~~~~~~~~ +It's extremely important to stop all DMA operations BEFORE attempting +to deallocate DMA control data. Failure to do so can result in memory +corruption, hangs, and on some chip-sets a hard crash. + +Stopping DMA after stopping the IRQs can avoid races where the +IRQ handler might restart DMA engines. + +While this step sounds obvious and trivial, several "mature" drivers +didn't get this step right in the past. + + +4.4 Release DMA buffers +~~~~~~~~~~~~~~~~~~~~~~~ +Once DMA is stopped, clean up streaming DMA first. +I.e. unmap data buffers and return buffers to "upstream" +owners if there is one. + +Then clean up "consistent" buffers which contain the control data. + +See Documentation/DMA-API.txt for details on unmapping interfaces. + + +4.5 Unregister from other subsystems +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Most low level PCI device drivers support some other subsystem +like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your +driver isn't losing resources from that other subsystem. +If this happens, typically the symptom is an Oops (panic) when +the subsystem attempts to call into a driver that has been unloaded. + + +4.6 Disable Device from responding to MMIO/IO Port addresses +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +io_unmap() MMIO or IO Port resources and then call pci_disable_device(). +This is the symmetric opposite of pci_enable_device(). +Do not access device registers after calling pci_disable_device(). + + +4.7 Release MMIO/IO Port Resource(s) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Call pci_release_region() to mark the MMIO or IO Port range as available. +Failure to do so usually results in the inability to reload the driver. + + + +5. How to access PCI config space +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +You can use pci_(read|write)_config_(byte|word|dword) to access the config +space of a device represented by struct pci_dev *. All these functions return 0 +when successful or an error code (PCIBIOS_...) which can be translated to a text +string by pcibios_strerror. Most drivers expect that accesses to valid PCI +devices don't fail. + +If you don't have a struct pci_dev available, you can call +pci_bus_(read|write)_config_(byte|word|dword) to access a given device +and function on that bus. + +If you access fields in the standard portion of the config header, please +use symbolic names of locations and bits declared in . + +If you need to access Extended PCI Capability registers, just call +pci_find_capability() for the particular capability and it will find the +corresponding register block for you. + + + +6. Other interesting functions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +pci_find_slot() Find pci_dev corresponding to given bus and + slot numbers. +pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3) +pci_find_capability() Find specified capability in device's capability + list. +pci_resource_start() Returns bus start address for a given PCI region +pci_resource_end() Returns bus end address for a given PCI region +pci_resource_len() Returns the byte length of a PCI region +pci_set_drvdata() Set private driver data pointer for a pci_dev +pci_get_drvdata() Return private driver data pointer for a pci_dev +pci_set_mwi() Enable Memory-Write-Invalidate transactions. +pci_clear_mwi() Disable Memory-Write-Invalidate transactions. + + + +7. Miscellaneous hints +~~~~~~~~~~~~~~~~~~~~~~ + +When displaying PCI device names to the user (for example when a driver wants +to tell the user what card has it found), please use pci_name(pci_dev). + +Always refer to the PCI devices by a pointer to the pci_dev structure. +All PCI layer functions use this identification and it's the only +reasonable one. Don't use bus/slot/function numbers except for very +special purposes -- on systems with multiple primary buses their semantics +can be pretty complex. + +Don't try to turn on Fast Back to Back writes in your driver. All devices +on the bus need to be capable of doing it, so this is something which needs +to be handled by platform and generic code, not individual drivers. + + + +8. Vendor and device identifications +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +One is not not required to add new device ids to include/linux/pci_ids.h. +Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids. + +PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary +hex numbers (vendor controlled) and normally used only in a single +location, the pci_device_id table. + +Please DO submit new vendor/device ids to pciids.sourceforge.net project. + + + +9. Obsolete functions +~~~~~~~~~~~~~~~~~~~~~ + +There are several functions which you might come across when trying to +port an old driver to the new PCI interface. They are no longer present +in the kernel as they aren't compatible with hotplug or PCI domains or +having sane locking. + +pci_find_device() Superseded by pci_get_device() +pci_find_subsys() Superseded by pci_get_subsys() +pci_find_slot() Superseded by pci_get_slot() + + +The alternative is the traditional PCI device driver that walks PCI +device lists. This is still possible but discouraged. + + + +10. MMIO Space and "Write Posting" +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Converting a driver from using I/O Port space to using MMIO space +often requires some additional changes. Specifically, "write posting" +needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2) +already do this. I/O Port space guarantees write transactions reach the PCI +device before the CPU can continue. Writes to MMIO space allow the CPU +to continue before the transaction reaches the PCI device. HW weenies +call this "Write Posting" because the write completion is "posted" to +the CPU before the transaction has reached its destination. + +Thus, timing sensitive code should add readl() where the CPU is +expected to wait before doing other work. The classic "bit banging" +sequence works fine for I/O Port space: + + for (i = 8; --i; val >>= 1) { + outb(val & 1, ioport_reg); /* write bit */ + udelay(10); + } + +The same sequence for MMIO space should be: + + for (i = 8; --i; val >>= 1) { + writeb(val & 1, mmio_reg); /* write bit */ + readb(safe_mmio_reg); /* flush posted write */ + udelay(10); + } + +It is important that "safe_mmio_reg" not have any side effects that +interferes with the correct operation of the device. + +Another case to watch out for is when resetting a PCI device. Use PCI +Configuration space reads to flush the writel(). This will gracefully +handle the PCI master abort on all platforms if the PCI device is +expected to not respond to a readl(). Most x86 platforms will allow +MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage +(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail"). + diff --git a/Documentation/PCI/pcieaer-howto.txt b/Documentation/PCI/pcieaer-howto.txt new file mode 100644 index 000000000000..16c251230c82 --- /dev/null +++ b/Documentation/PCI/pcieaer-howto.txt @@ -0,0 +1,253 @@ + The PCI Express Advanced Error Reporting Driver Guide HOWTO + T. Long Nguyen + Yanmin Zhang + 07/29/2006 + + +1. Overview + +1.1 About this guide + +This guide describes the basics of the PCI Express Advanced Error +Reporting (AER) driver and provides information on how to use it, as +well as how to enable the drivers of endpoint devices to conform with +PCI Express AER driver. + +1.2 Copyright © Intel Corporation 2006. + +1.3 What is the PCI Express AER Driver? + +PCI Express error signaling can occur on the PCI Express link itself +or on behalf of transactions initiated on the link. PCI Express +defines two error reporting paradigms: the baseline capability and +the Advanced Error Reporting capability. The baseline capability is +required of all PCI Express components providing a minimum defined +set of error reporting requirements. Advanced Error Reporting +capability is implemented with a PCI Express advanced error reporting +extended capability structure providing more robust error reporting. + +The PCI Express AER driver provides the infrastructure to support PCI +Express Advanced Error Reporting capability. The PCI Express AER +driver provides three basic functions: + +- Gathers the comprehensive error information if errors occurred. +- Reports error to the users. +- Performs error recovery actions. + +AER driver only attaches root ports which support PCI-Express AER +capability. + + +2. User Guide + +2.1 Include the PCI Express AER Root Driver into the Linux Kernel + +The PCI Express AER Root driver is a Root Port service driver attached +to the PCI Express Port Bus driver. If a user wants to use it, the driver +has to be compiled. Option CONFIG_PCIEAER supports this capability. It +depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and +CONFIG_PCIEAER = y. + +2.2 Load PCI Express AER Root Driver +There is a case where a system has AER support in BIOS. Enabling the AER +Root driver and having AER support in BIOS may result unpredictable +behavior. To avoid this conflict, a successful load of the AER Root driver +requires ACPI _OSC support in the BIOS to allow the AER Root driver to +request for native control of AER. See the PCI FW 3.0 Specification for +details regarding OSC usage. Currently, lots of firmwares don't provide +_OSC support while they use PCI Express. To support such firmwares, +forceload, a parameter of type bool, could enable AER to continue to +be initiated although firmwares have no _OSC support. To enable the +walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line +when booting kernel. Note that forceload=n by default. + +2.3 AER error output +When a PCI-E AER error is captured, an error message will be outputed to +console. If it's a correctable error, it is outputed as a warning. +Otherwise, it is printed as an error. So users could choose different +log level to filter out correctable error messages. + +Below shows an example. ++------ PCI-Express Device Error -----+ +Error Severity : Uncorrected (Fatal) +PCIE Bus Error type : Transaction Layer +Unsupported Request : First +Requester ID : 0500 +VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h +TLB Header: +04000001 00200a03 05010000 00050100 + +In the example, 'Requester ID' means the ID of the device who sends +the error message to root port. Pls. refer to pci express specs for +other fields. + + +3. Developer Guide + +To enable AER aware support requires a software driver to configure +the AER capability structure within its device and to provide callbacks. + +To support AER better, developers need understand how AER does work +firstly. + +PCI Express errors are classified into two types: correctable errors +and uncorrectable errors. This classification is based on the impacts +of those errors, which may result in degraded performance or function +failure. + +Correctable errors pose no impacts on the functionality of the +interface. The PCI Express protocol can recover without any software +intervention or any loss of data. These errors are detected and +corrected by hardware. Unlike correctable errors, uncorrectable +errors impact functionality of the interface. Uncorrectable errors +can cause a particular transaction or a particular PCI Express link +to be unreliable. Depending on those error conditions, uncorrectable +errors are further classified into non-fatal errors and fatal errors. +Non-fatal errors cause the particular transaction to be unreliable, +but the PCI Express link itself is fully functional. Fatal errors, on +the other hand, cause the link to be unreliable. + +When AER is enabled, a PCI Express device will automatically send an +error message to the PCIE root port above it when the device captures +an error. The Root Port, upon receiving an error reporting message, +internally processes and logs the error message in its PCI Express +capability structure. Error information being logged includes storing +the error reporting agent's requestor ID into the Error Source +Identification Registers and setting the error bits of the Root Error +Status Register accordingly. If AER error reporting is enabled in Root +Error Command Register, the Root Port generates an interrupt if an +error is detected. + +Note that the errors as described above are related to the PCI Express +hierarchy and links. These errors do not include any device specific +errors because device specific errors will still get sent directly to +the device driver. + +3.1 Configure the AER capability structure + +AER aware drivers of PCI Express component need change the device +control registers to enable AER. They also could change AER registers, +including mask and severity registers. Helper function +pci_enable_pcie_error_reporting could be used to enable AER. See +section 3.3. + +3.2. Provide callbacks + +3.2.1 callback reset_link to reset pci express link + +This callback is used to reset the pci express physical link when a +fatal error happens. The root port aer service driver provides a +default reset_link function, but different upstream ports might +have different specifications to reset pci express link, so all +upstream ports should provide their own reset_link functions. + +In struct pcie_port_service_driver, a new pointer, reset_link, is +added. + +pci_ers_result_t (*reset_link) (struct pci_dev *dev); + +Section 3.2.2.2 provides more detailed info on when to call +reset_link. + +3.2.2 PCI error-recovery callbacks + +The PCI Express AER Root driver uses error callbacks to coordinate +with downstream device drivers associated with a hierarchy in question +when performing error recovery actions. + +Data struct pci_driver has a pointer, err_handler, to point to +pci_error_handlers who consists of a couple of callback function +pointers. AER driver follows the rules defined in +pci-error-recovery.txt except pci express specific parts (e.g. +reset_link). Pls. refer to pci-error-recovery.txt for detailed +definitions of the callbacks. + +Below sections specify when to call the error callback functions. + +3.2.2.1 Correctable errors + +Correctable errors pose no impacts on the functionality of +the interface. The PCI Express protocol can recover without any +software intervention or any loss of data. These errors do not +require any recovery actions. The AER driver clears the device's +correctable error status register accordingly and logs these errors. + +3.2.2.2 Non-correctable (non-fatal and fatal) errors + +If an error message indicates a non-fatal error, performing link reset +at upstream is not required. The AER driver calls error_detected(dev, +pci_channel_io_normal) to all drivers associated within a hierarchy in +question. for example, +EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort. +If Upstream port A captures an AER error, the hierarchy consists of +Downstream port B and EndPoint. + +A driver may return PCI_ERS_RESULT_CAN_RECOVER, +PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on +whether it can recover or the AER driver calls mmio_enabled as next. + +If an error message indicates a fatal error, kernel will broadcast +error_detected(dev, pci_channel_io_frozen) to all drivers within +a hierarchy in question. Then, performing link reset at upstream is +necessary. As different kinds of devices might use different approaches +to reset link, AER port service driver is required to provide the +function to reset link. Firstly, kernel looks for if the upstream +component has an aer driver. If it has, kernel uses the reset_link +callback of the aer driver. If the upstream component has no aer driver +and the port is downstream port, we will use the aer driver of the +root port who reports the AER error. As for upstream ports, +they should provide their own aer service drivers with reset_link +function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and +reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes +to mmio_enabled. + +3.3 helper functions + +3.3.1 int pci_find_aer_capability(struct pci_dev *dev); +pci_find_aer_capability locates the PCI Express AER capability +in the device configuration space. If the device doesn't support +PCI-Express AER, the function returns 0. + +3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev); +pci_enable_pcie_error_reporting enables the device to send error +messages to root port when an error is detected. Note that devices +don't enable the error reporting by default, so device drivers need +call this function to enable it. + +3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev); +pci_disable_pcie_error_reporting disables the device to send error +messages to root port when an error is detected. + +3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); +pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable +error status register. + +3.4 Frequent Asked Questions + +Q: What happens if a PCI Express device driver does not provide an +error recovery handler (pci_driver->err_handler is equal to NULL)? + +A: The devices attached with the driver won't be recovered. If the +error is fatal, kernel will print out warning messages. Please refer +to section 3 for more information. + +Q: What happens if an upstream port service driver does not provide +callback reset_link? + +A: Fatal error recovery will fail if the errors are reported by the +upstream ports who are attached by the service driver. + +Q: How does this infrastructure deal with driver that is not PCI +Express aware? + +A: This infrastructure calls the error callback functions of the +driver when an error happens. But if the driver is not aware of +PCI Express, the device might not report its own errors to root +port. + +Q: What modifications will that driver need to make it compatible +with the PCI Express AER Root driver? + +A: It could call the helper functions to enable AER in devices and +cleanup uncorrectable status register. Pls. refer to section 3.3. + diff --git a/Documentation/PCIEBUS-HOWTO.txt b/Documentation/PCIEBUS-HOWTO.txt deleted file mode 100644 index c93f42a74d7e..000000000000 --- a/Documentation/PCIEBUS-HOWTO.txt +++ /dev/null @@ -1,217 +0,0 @@ - The PCI Express Port Bus Driver Guide HOWTO - Tom L Nguyen tom.l.nguyen@intel.com - 11/03/2004 - -1. About this guide - -This guide describes the basics of the PCI Express Port Bus driver -and provides information on how to enable the service drivers to -register/unregister with the PCI Express Port Bus Driver. - -2. Copyright 2004 Intel Corporation - -3. What is the PCI Express Port Bus Driver - -A PCI Express Port is a logical PCI-PCI Bridge structure. There -are two types of PCI Express Port: the Root Port and the Switch -Port. The Root Port originates a PCI Express link from a PCI Express -Root Complex and the Switch Port connects PCI Express links to -internal logical PCI buses. The Switch Port, which has its secondary -bus representing the switch's internal routing logic, is called the -switch's Upstream Port. The switch's Downstream Port is bridging from -switch's internal routing bus to a bus representing the downstream -PCI Express link from the PCI Express Switch. - -A PCI Express Port can provide up to four distinct functions, -referred to in this document as services, depending on its port type. -PCI Express Port's services include native hotplug support (HP), -power management event support (PME), advanced error reporting -support (AER), and virtual channel support (VC). These services may -be handled by a single complex driver or be individually distributed -and handled by corresponding service drivers. - -4. Why use the PCI Express Port Bus Driver? - -In existing Linux kernels, the Linux Device Driver Model allows a -physical device to be handled by only a single driver. The PCI -Express Port is a PCI-PCI Bridge device with multiple distinct -services. To maintain a clean and simple solution each service -may have its own software service driver. In this case several -service drivers will compete for a single PCI-PCI Bridge device. -For example, if the PCI Express Root Port native hotplug service -driver is loaded first, it claims a PCI-PCI Bridge Root Port. The -kernel therefore does not load other service drivers for that Root -Port. In other words, it is impossible to have multiple service -drivers load and run on a PCI-PCI Bridge device simultaneously -using the current driver model. - -To enable multiple service drivers running simultaneously requires -having a PCI Express Port Bus driver, which manages all populated -PCI Express Ports and distributes all provided service requests -to the corresponding service drivers as required. Some key -advantages of using the PCI Express Port Bus driver are listed below: - - - Allow multiple service drivers to run simultaneously on - a PCI-PCI Bridge Port device. - - - Allow service drivers implemented in an independent - staged approach. - - - Allow one service driver to run on multiple PCI-PCI Bridge - Port devices. - - - Manage and distribute resources of a PCI-PCI Bridge Port - device to requested service drivers. - -5. Configuring the PCI Express Port Bus Driver vs. Service Drivers - -5.1 Including the PCI Express Port Bus Driver Support into the Kernel - -Including the PCI Express Port Bus driver depends on whether the PCI -Express support is included in the kernel config. The kernel will -automatically include the PCI Express Port Bus driver as a kernel -driver when the PCI Express support is enabled in the kernel. - -5.2 Enabling Service Driver Support - -PCI device drivers are implemented based on Linux Device Driver Model. -All service drivers are PCI device drivers. As discussed above, it is -impossible to load any service driver once the kernel has loaded the -PCI Express Port Bus Driver. To meet the PCI Express Port Bus Driver -Model requires some minimal changes on existing service drivers that -imposes no impact on the functionality of existing service drivers. - -A service driver is required to use the two APIs shown below to -register its service with the PCI Express Port Bus driver (see -section 5.2.1 & 5.2.2). It is important that a service driver -initializes the pcie_port_service_driver data structure, included in -header file /include/linux/pcieport_if.h, before calling these APIs. -Failure to do so will result an identity mismatch, which prevents -the PCI Express Port Bus driver from loading a service driver. - -5.2.1 pcie_port_service_register - -int pcie_port_service_register(struct pcie_port_service_driver *new) - -This API replaces the Linux Driver Model's pci_module_init API. A -service driver should always calls pcie_port_service_register at -module init. Note that after service driver being loaded, calls -such as pci_enable_device(dev) and pci_set_master(dev) are no longer -necessary since these calls are executed by the PCI Port Bus driver. - -5.2.2 pcie_port_service_unregister - -void pcie_port_service_unregister(struct pcie_port_service_driver *new) - -pcie_port_service_unregister replaces the Linux Driver Model's -pci_unregister_driver. It's always called by service driver when a -module exits. - -5.2.3 Sample Code - -Below is sample service driver code to initialize the port service -driver data structure. - -static struct pcie_port_service_id service_id[] = { { - .vendor = PCI_ANY_ID, - .device = PCI_ANY_ID, - .port_type = PCIE_RC_PORT, - .service_type = PCIE_PORT_SERVICE_AER, - }, { /* end: all zeroes */ } -}; - -static struct pcie_port_service_driver root_aerdrv = { - .name = (char *)device_name, - .id_table = &service_id[0], - - .probe = aerdrv_load, - .remove = aerdrv_unload, - - .suspend = aerdrv_suspend, - .resume = aerdrv_resume, -}; - -Below is a sample code for registering/unregistering a service -driver. - -static int __init aerdrv_service_init(void) -{ - int retval = 0; - - retval = pcie_port_service_register(&root_aerdrv); - if (!retval) { - /* - * FIX ME - */ - } - return retval; -} - -static void __exit aerdrv_service_exit(void) -{ - pcie_port_service_unregister(&root_aerdrv); -} - -module_init(aerdrv_service_init); -module_exit(aerdrv_service_exit); - -6. Possible Resource Conflicts - -Since all service drivers of a PCI-PCI Bridge Port device are -allowed to run simultaneously, below lists a few of possible resource -conflicts with proposed solutions. - -6.1 MSI Vector Resource - -The MSI capability structure enables a device software driver to call -pci_enable_msi to request MSI based interrupts. Once MSI interrupts -are enabled on a device, it stays in this mode until a device driver -calls pci_disable_msi to disable MSI interrupts and revert back to -INTx emulation mode. Since service drivers of the same PCI-PCI Bridge -port share the same physical device, if an individual service driver -calls pci_enable_msi/pci_disable_msi it may result unpredictable -behavior. For example, two service drivers run simultaneously on the -same physical Root Port. Both service drivers call pci_enable_msi to -request MSI based interrupts. A service driver may not know whether -any other service drivers have run on this Root Port. If either one -of them calls pci_disable_msi, it puts the other service driver -in a wrong interrupt mode. - -To avoid this situation all service drivers are not permitted to -switch interrupt mode on its device. The PCI Express Port Bus driver -is responsible for determining the interrupt mode and this should be -transparent to service drivers. Service drivers need to know only -the vector IRQ assigned to the field irq of struct pcie_device, which -is passed in when the PCI Express Port Bus driver probes each service -driver. Service drivers should use (struct pcie_device*)dev->irq to -call request_irq/free_irq. In addition, the interrupt mode is stored -in the field interrupt_mode of struct pcie_device. - -6.2 MSI-X Vector Resources - -Similar to the MSI a device driver for an MSI-X capable device can -call pci_enable_msix to request MSI-X interrupts. All service drivers -are not permitted to switch interrupt mode on its device. The PCI -Express Port Bus driver is responsible for determining the interrupt -mode and this should be transparent to service drivers. Any attempt -by service driver to call pci_enable_msix/pci_disable_msix may -result unpredictable behavior. Service drivers should use -(struct pcie_device*)dev->irq and call request_irq/free_irq. - -6.3 PCI Memory/IO Mapped Regions - -Service drivers for PCI Express Power Management (PME), Advanced -Error Reporting (AER), Hot-Plug (HP) and Virtual Channel (VC) access -PCI configuration space on the PCI Express port. In all cases the -registers accessed are independent of each other. This patch assumes -that all service drivers will be well behaved and not overwrite -other service driver's configuration settings. - -6.4 PCI Config Registers - -Each service driver runs its PCI config operations on its own -capability structure except the PCI Express capability structure, in -which Root Control register and Device Control register are shared -between PME and AER. This patch assumes that all service drivers -will be well behaved and not overwrite other service driver's -configuration settings. diff --git a/Documentation/memory-barriers.txt b/Documentation/memory-barriers.txt index 1f506f7830ec..e5a819a4f0c9 100644 --- a/Documentation/memory-barriers.txt +++ b/Documentation/memory-barriers.txt @@ -430,8 +430,8 @@ There are certain things that the Linux kernel memory barriers do not guarantee: [*] For information on bus mastering DMA and coherency please read: - Documentation/pci.txt - Documentation/DMA-mapping.txt + Documentation/PCI/pci.txt + Documentation/PCI/PCI-DMA-mapping.txt Documentation/DMA-API.txt diff --git a/Documentation/pci-error-recovery.txt b/Documentation/pci-error-recovery.txt deleted file mode 100644 index 6650af432523..000000000000 --- a/Documentation/pci-error-recovery.txt +++ /dev/null @@ -1,396 +0,0 @@ - - PCI Error Recovery - ------------------ - February 2, 2006 - - Current document maintainer: - Linas Vepstas - - -Many PCI bus controllers are able to detect a variety of hardware -PCI errors on the bus, such as parity errors on the data and address -busses, as well as SERR and PERR errors. Some of the more advanced -chipsets are able to deal with these errors; these include PCI-E chipsets, -and the PCI-host bridges found on IBM Power4 and Power5-based pSeries -boxes. A typical action taken is to disconnect the affected device, -halting all I/O to it. The goal of a disconnection is to avoid system -corruption; for example, to halt system memory corruption due to DMA's -to "wild" addresses. Typically, a reconnection mechanism is also -offered, so that the affected PCI device(s) are reset and put back -into working condition. The reset phase requires coordination -between the affected device drivers and the PCI controller chip. -This document describes a generic API for notifying device drivers -of a bus disconnection, and then performing error recovery. -This API is currently implemented in the 2.6.16 and later kernels. - -Reporting and recovery is performed in several steps. First, when -a PCI hardware error has resulted in a bus disconnect, that event -is reported as soon as possible to all affected device drivers, -including multiple instances of a device driver on multi-function -cards. This allows device drivers to avoid deadlocking in spinloops, -waiting for some i/o-space register to change, when it never will. -It also gives the drivers a chance to defer incoming I/O as -needed. - -Next, recovery is performed in several stages. Most of the complexity -is forced by the need to handle multi-function devices, that is, -devices that have multiple device drivers associated with them. -In the first stage, each driver is allowed to indicate what type -of reset it desires, the choices being a simple re-enabling of I/O -or requesting a hard reset (a full electrical #RST of the PCI card). -If any driver requests a full reset, that is what will be done. - -After a full reset and/or a re-enabling of I/O, all drivers are -again notified, so that they may then perform any device setup/config -that may be required. After these have all completed, a final -"resume normal operations" event is sent out. - -The biggest reason for choosing a kernel-based implementation rather -than a user-space implementation was the need to deal with bus -disconnects of PCI devices attached to storage media, and, in particular, -disconnects from devices holding the root file system. If the root -file system is disconnected, a user-space mechanism would have to go -through a large number of contortions to complete recovery. Almost all -of the current Linux file systems are not tolerant of disconnection -from/reconnection to their underlying block device. By contrast, -bus errors are easy to manage in the device driver. Indeed, most -device drivers already handle very similar recovery procedures; -for example, the SCSI-generic layer already provides significant -mechanisms for dealing with SCSI bus errors and SCSI bus resets. - - -Detailed Design ---------------- -Design and implementation details below, based on a chain of -public email discussions with Ben Herrenschmidt, circa 5 April 2005. - -The error recovery API support is exposed to the driver in the form of -a structure of function pointers pointed to by a new field in struct -pci_driver. A driver that fails to provide the structure is "non-aware", -and the actual recovery steps taken are platform dependent. The -arch/powerpc implementation will simulate a PCI hotplug remove/add. - -This structure has the form: -struct pci_error_handlers -{ - int (*error_detected)(struct pci_dev *dev, enum pci_channel_state); - int (*mmio_enabled)(struct pci_dev *dev); - int (*link_reset)(struct pci_dev *dev); - int (*slot_reset)(struct pci_dev *dev); - void (*resume)(struct pci_dev *dev); -}; - -The possible channel states are: -enum pci_channel_state { - pci_channel_io_normal, /* I/O channel is in normal state */ - pci_channel_io_frozen, /* I/O to channel is blocked */ - pci_channel_io_perm_failure, /* PCI card is dead */ -}; - -Possible return values are: -enum pci_ers_result { - PCI_ERS_RESULT_NONE, /* no result/none/not supported in device driver */ - PCI_ERS_RESULT_CAN_RECOVER, /* Device driver can recover without slot reset */ - PCI_ERS_RESULT_NEED_RESET, /* Device driver wants slot to be reset. */ - PCI_ERS_RESULT_DISCONNECT, /* Device has completely failed, is unrecoverable */ - PCI_ERS_RESULT_RECOVERED, /* Device driver is fully recovered and operational */ -}; - -A driver does not have to implement all of these callbacks; however, -if it implements any, it must implement error_detected(). If a callback -is not implemented, the corresponding feature is considered unsupported. -For example, if mmio_enabled() and resume() aren't there, then it -is assumed that the driver is not doing any direct recovery and requires -a reset. If link_reset() is not implemented, the card is assumed as -not care about link resets. Typically a driver will want to know about -a slot_reset(). - -The actual steps taken by a platform to recover from a PCI error -event will be platform-dependent, but will follow the general -sequence described below. - -STEP 0: Error Event -------------------- -PCI bus error is detect by the PCI hardware. On powerpc, the slot -is isolated, in that all I/O is blocked: all reads return 0xffffffff, -all writes are ignored. - - -STEP 1: Notification --------------------- -Platform calls the error_detected() callback on every instance of -every driver affected by the error. - -At this point, the device might not be accessible anymore, depending on -the platform (the slot will be isolated on powerpc). The driver may -already have "noticed" the error because of a failing I/O, but this -is the proper "synchronization point", that is, it gives the driver -a chance to cleanup, waiting for pending stuff (timers, whatever, etc...) -to complete; it can take semaphores, schedule, etc... everything but -touch the device. Within this function and after it returns, the driver -shouldn't do any new IOs. Called in task context. This is sort of a -"quiesce" point. See note about interrupts at the end of this doc. - -All drivers participating in this system must implement this call. -The driver must return one of the following result codes: - - PCI_ERS_RESULT_CAN_RECOVER: - Driver returns this if it thinks it might be able to recover - the HW by just banging IOs or if it wants to be given - a chance to extract some diagnostic information (see - mmio_enable, below). - - PCI_ERS_RESULT_NEED_RESET: - Driver returns this if it can't recover without a hard - slot reset. - - PCI_ERS_RESULT_DISCONNECT: - Driver returns this if it doesn't want to recover at all. - -The next step taken will depend on the result codes returned by the -drivers. - -If all drivers on the segment/slot return PCI_ERS_RESULT_CAN_RECOVER, -then the platform should re-enable IOs on the slot (or do nothing in -particular, if the platform doesn't isolate slots), and recovery -proceeds to STEP 2 (MMIO Enable). - -If any driver requested a slot reset (by returning PCI_ERS_RESULT_NEED_RESET), -then recovery proceeds to STEP 4 (Slot Reset). - -If the platform is unable to recover the slot, the next step -is STEP 6 (Permanent Failure). - ->>> The current powerpc implementation assumes that a device driver will ->>> *not* schedule or semaphore in this routine; the current powerpc ->>> implementation uses one kernel thread to notify all devices; ->>> thus, if one device sleeps/schedules, all devices are affected. ->>> Doing better requires complex multi-threaded logic in the error ->>> recovery implementation (e.g. waiting for all notification threads ->>> to "join" before proceeding with recovery.) This seems excessively ->>> complex and not worth implementing. - ->>> The current powerpc implementation doesn't much care if the device ->>> attempts I/O at this point, or not. I/O's will fail, returning ->>> a value of 0xff on read, and writes will be dropped. If the device ->>> driver attempts more than 10K I/O's to a frozen adapter, it will ->>> assume that the device driver has gone into an infinite loop, and ->>> it will panic the kernel. There doesn't seem to be any other ->>> way of stopping a device driver that insists on spinning on I/O. - -STEP 2: MMIO Enabled -------------------- -The platform re-enables MMIO to the device (but typically not the -DMA), and then calls the mmio_enabled() callback on all affected -device drivers. - -This is the "early recovery" call. IOs are allowed again, but DMA is -not (hrm... to be discussed, I prefer not), with some restrictions. This -is NOT a callback for the driver to start operations again, only to -peek/poke at the device, extract diagnostic information, if any, and -eventually do things like trigger a device local reset or some such, -but not restart operations. This is callback is made if all drivers on -a segment agree that they can try to recover and if no automatic link reset -was performed by the HW. If the platform can't just re-enable IOs without -a slot reset or a link reset, it wont call this callback, and instead -will have gone directly to STEP 3 (Link Reset) or STEP 4 (Slot Reset) - ->>> The following is proposed; no platform implements this yet: ->>> Proposal: All I/O's should be done _synchronously_ from within ->>> this callback, errors triggered by them will be returned via ->>> the normal pci_check_whatever() API, no new error_detected() ->>> callback will be issued due to an error happening here. However, ->>> such an error might cause IOs to be re-blocked for the whole ->>> segment, and thus invalidate the recovery that other devices ->>> on the same segment might have done, forcing the whole segment ->>> into one of the next states, that is, link reset or slot reset. - -The driver should return one of the following result codes: - - PCI_ERS_RESULT_RECOVERED - Driver returns this if it thinks the device is fully - functional and thinks it is ready to start - normal driver operations again. There is no - guarantee that the driver will actually be - allowed to proceed, as another driver on the - same segment might have failed and thus triggered a - slot reset on platforms that support it. - - - PCI_ERS_RESULT_NEED_RESET - Driver returns this if it thinks the device is not - recoverable in it's current state and it needs a slot - reset to proceed. - - - PCI_ERS_RESULT_DISCONNECT - Same as above. Total failure, no recovery even after - reset driver dead. (To be defined more precisely) - -The next step taken depends on the results returned by the drivers. -If all drivers returned PCI_ERS_RESULT_RECOVERED, then the platform -proceeds to either STEP3 (Link Reset) or to STEP 5 (Resume Operations). - -If any driver returned PCI_ERS_RESULT_NEED_RESET, then the platform -proceeds to STEP 4 (Slot Reset) - ->>> The current powerpc implementation does not implement this callback. - - -STEP 3: Link Reset ------------------- -The platform resets the link, and then calls the link_reset() callback -on all affected device drivers. This is a PCI-Express specific state -and is done whenever a non-fatal error has been detected that can be -"solved" by resetting the link. This call informs the driver of the -reset and the driver should check to see if the device appears to be -in working condition. - -The driver is not supposed to restart normal driver I/O operations -at this point. It should limit itself to "probing" the device to -check it's recoverability status. If all is right, then the platform -will call resume() once all drivers have ack'd link_reset(). - - Result codes: - (identical to STEP 3 (MMIO Enabled) - -The platform then proceeds to either STEP 4 (Slot Reset) or STEP 5 -(Resume Operations). - ->>> The current powerpc implementation does not implement this callback. - - -STEP 4: Slot Reset ------------------- -The platform performs a soft or hard reset of the device, and then -calls the slot_reset() callback. - -A soft reset consists of asserting the adapter #RST line and then -restoring the PCI BAR's and PCI configuration header to a state -that is equivalent to what it would be after a fresh system -power-on followed by power-on BIOS/system firmware initialization. -If the platform supports PCI hotplug, then the reset might be -performed by toggling the slot electrical power off/on. - -It is important for the platform to restore the PCI config space -to the "fresh poweron" state, rather than the "last state". After -a slot reset, the device driver will almost always use its standard -device initialization routines, and an unusual config space setup -may result in hung devices, kernel panics, or silent data corruption. - -This call gives drivers the chance to re-initialize the hardware -(re-download firmware, etc.). At this point, the driver may assume -that he card is in a fresh state and is fully functional. In -particular, interrupt generation should work normally. - -Drivers should not yet restart normal I/O processing operations -at this point. If all device drivers report success on this -callback, the platform will call resume() to complete the sequence, -and let the driver restart normal I/O processing. - -A driver can still return a critical failure for this function if -it can't get the device operational after reset. If the platform -previously tried a soft reset, it might now try a hard reset (power -cycle) and then call slot_reset() again. It the device still can't -be recovered, there is nothing more that can be done; the platform -will typically report a "permanent failure" in such a case. The -device will be considered "dead" in this case. - -Drivers for multi-function cards will need to coordinate among -themselves as to which driver instance will perform any "one-shot" -or global device initialization. For example, the Symbios sym53cxx2 -driver performs device init only from PCI function 0: - -+ if (PCI_FUNC(pdev->devfn) == 0) -+ sym_reset_scsi_bus(np, 0); - - Result codes: - - PCI_ERS_RESULT_DISCONNECT - Same as above. - -Platform proceeds either to STEP 5 (Resume Operations) or STEP 6 (Permanent -Failure). - ->>> The current powerpc implementation does not currently try a ->>> power-cycle reset if the driver returned PCI_ERS_RESULT_DISCONNECT. ->>> However, it probably should. - - -STEP 5: Resume Operations -------------------------- -The platform will call the resume() callback on all affected device -drivers if all drivers on the segment have returned -PCI_ERS_RESULT_RECOVERED from one of the 3 previous callbacks. -The goal of this callback is to tell the driver to restart activity, -that everything is back and running. This callback does not return -a result code. - -At this point, if a new error happens, the platform will restart -a new error recovery sequence. - -STEP 6: Permanent Failure -------------------------- -A "permanent failure" has occurred, and the platform cannot recover -the device. The platform will call error_detected() with a -pci_channel_state value of pci_channel_io_perm_failure. - -The device driver should, at this point, assume the worst. It should -cancel all pending I/O, refuse all new I/O, returning -EIO to -higher layers. The device driver should then clean up all of its -memory and remove itself from kernel operations, much as it would -during system shutdown. - -The platform will typically notify the system operator of the -permanent failure in some way. If the device is hotplug-capable, -the operator will probably want to remove and replace the device. -Note, however, not all failures are truly "permanent". Some are -caused by over-heating, some by a poorly seated card. Many -PCI error events are caused by software bugs, e.g. DMA's to -wild addresses or bogus split transactions due to programming -errors. See the discussion in powerpc/eeh-pci-error-recovery.txt -for additional detail on real-life experience of the causes of -software errors. - - -Conclusion; General Remarks ---------------------------- -The way those callbacks are called is platform policy. A platform with -no slot reset capability may want to just "ignore" drivers that can't -recover (disconnect them) and try to let other cards on the same segment -recover. Keep in mind that in most real life cases, though, there will -be only one driver per segment. - -Now, a note about interrupts. If you get an interrupt and your -device is dead or has been isolated, there is a problem :) -The current policy is to turn this into a platform policy. -That is, the recovery API only requires that: - - - There is no guarantee that interrupt delivery can proceed from any -device on the segment starting from the error detection and until the -resume callback is sent, at which point interrupts are expected to be -fully operational. - - - There is no guarantee that interrupt delivery is stopped, that is, -a driver that gets an interrupt after detecting an error, or that detects -an error within the interrupt handler such that it prevents proper -ack'ing of the interrupt (and thus removal of the source) should just -return IRQ_NOTHANDLED. It's up to the platform to deal with that -condition, typically by masking the IRQ source during the duration of -the error handling. It is expected that the platform "knows" which -interrupts are routed to error-management capable slots and can deal -with temporarily disabling that IRQ number during error processing (this -isn't terribly complex). That means some IRQ latency for other devices -sharing the interrupt, but there is simply no other way. High end -platforms aren't supposed to share interrupts between many devices -anyway :) - ->>> Implementation details for the powerpc platform are discussed in ->>> the file Documentation/powerpc/eeh-pci-error-recovery.txt - ->>> As of this writing, there are six device drivers with patches ->>> implementing error recovery. Not all of these patches are in ->>> mainline yet. These may be used as "examples": ->>> ->>> drivers/scsi/ipr.c ->>> drivers/scsi/sym53cxx_2 ->>> drivers/next/e100.c ->>> drivers/net/e1000 ->>> drivers/net/ixgb ->>> drivers/net/s2io.c - -The End -------- diff --git a/Documentation/pci.txt b/Documentation/pci.txt deleted file mode 100644 index d2c2e6e2b224..000000000000 --- a/Documentation/pci.txt +++ /dev/null @@ -1,646 +0,0 @@ - - How To Write Linux PCI Drivers - - by Martin Mares on 07-Feb-2000 - updated by Grant Grundler on 23-Dec-2006 - -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The world of PCI is vast and full of (mostly unpleasant) surprises. -Since each CPU architecture implements different chip-sets and PCI devices -have different requirements (erm, "features"), the result is the PCI support -in the Linux kernel is not as trivial as one would wish. This short paper -tries to introduce all potential driver authors to Linux APIs for -PCI device drivers. - -A more complete resource is the third edition of "Linux Device Drivers" -by Jonathan Corbet, Alessandro Rubini, and Greg Kroah-Hartman. -LDD3 is available for free (under Creative Commons License) from: - - http://lwn.net/Kernel/LDD3/ - -However, keep in mind that all documents are subject to "bit rot". -Refer to the source code if things are not working as described here. - -Please send questions/comments/patches about Linux PCI API to the -"Linux PCI" mailing list. - - - -0. Structure of PCI drivers -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -PCI drivers "discover" PCI devices in a system via pci_register_driver(). -Actually, it's the other way around. When the PCI generic code discovers -a new device, the driver with a matching "description" will be notified. -Details on this below. - -pci_register_driver() leaves most of the probing for devices to -the PCI layer and supports online insertion/removal of devices [thus -supporting hot-pluggable PCI, CardBus, and Express-Card in a single driver]. -pci_register_driver() call requires passing in a table of function -pointers and thus dictates the high level structure of a driver. - -Once the driver knows about a PCI device and takes ownership, the -driver generally needs to perform the following initialization: - - Enable the device - Request MMIO/IOP resources - Set the DMA mask size (for both coherent and streaming DMA) - Allocate and initialize shared control data (pci_allocate_coherent()) - Access device configuration space (if needed) - Register IRQ handler (request_irq()) - Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip) - Enable DMA/processing engines - -When done using the device, and perhaps the module needs to be unloaded, -the driver needs to take the follow steps: - Disable the device from generating IRQs - Release the IRQ (free_irq()) - Stop all DMA activity - Release DMA buffers (both streaming and coherent) - Unregister from other subsystems (e.g. scsi or netdev) - Release MMIO/IOP resources - Disable the device - -Most of these topics are covered in the following sections. -For the rest look at LDD3 or . - -If the PCI subsystem is not configured (CONFIG_PCI is not set), most of -the PCI functions described below are defined as inline functions either -completely empty or just returning an appropriate error codes to avoid -lots of ifdefs in the drivers. - - - -1. pci_register_driver() call -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -PCI device drivers call pci_register_driver() during their -initialization with a pointer to a structure describing the driver -(struct pci_driver): - - field name Description - ---------- ------------------------------------------------------ - id_table Pointer to table of device ID's the driver is - interested in. Most drivers should export this - table using MODULE_DEVICE_TABLE(pci,...). - - probe This probing function gets called (during execution - of pci_register_driver() for already existing - devices or later if a new device gets inserted) for - all PCI devices which match the ID table and are not - "owned" by the other drivers yet. This function gets - passed a "struct pci_dev *" for each device whose - entry in the ID table matches the device. The probe - function returns zero when the driver chooses to - take "ownership" of the device or an error code - (negative number) otherwise. - The probe function always gets called from process - context, so it can sleep. - - remove The remove() function gets called whenever a device - being handled by this driver is removed (either during - deregistration of the driver or when it's manually - pulled out of a hot-pluggable slot). - The remove function always gets called from process - context, so it can sleep. - - suspend Put device into low power state. - suspend_late Put device into low power state. - - resume_early Wake device from low power state. - resume Wake device from low power state. - - (Please see Documentation/power/pci.txt for descriptions - of PCI Power Management and the related functions.) - - shutdown Hook into reboot_notifier_list (kernel/sys.c). - Intended to stop any idling DMA operations. - Useful for enabling wake-on-lan (NIC) or changing - the power state of a device before reboot. - e.g. drivers/net/e100.c. - - err_handler See Documentation/pci-error-recovery.txt - - -The ID table is an array of struct pci_device_id entries ending with an -all-zero entry; use of the macro DEFINE_PCI_DEVICE_TABLE is the preferred -method of declaring the table. Each entry consists of: - - vendor,device Vendor and device ID to match (or PCI_ANY_ID) - - subvendor, Subsystem vendor and device ID to match (or PCI_ANY_ID) - subdevice, - - class Device class, subclass, and "interface" to match. - See Appendix D of the PCI Local Bus Spec or - include/linux/pci_ids.h for a full list of classes. - Most drivers do not need to specify class/class_mask - as vendor/device is normally sufficient. - - class_mask limit which sub-fields of the class field are compared. - See drivers/scsi/sym53c8xx_2/ for example of usage. - - driver_data Data private to the driver. - Most drivers don't need to use driver_data field. - Best practice is to use driver_data as an index - into a static list of equivalent device types, - instead of using it as a pointer. - - -Most drivers only need PCI_DEVICE() or PCI_DEVICE_CLASS() to set up -a pci_device_id table. - -New PCI IDs may be added to a device driver pci_ids table at runtime -as shown below: - -echo "vendor device subvendor subdevice class class_mask driver_data" > \ -/sys/bus/pci/drivers/{driver}/new_id - -All fields are passed in as hexadecimal values (no leading 0x). -The vendor and device fields are mandatory, the others are optional. Users -need pass only as many optional fields as necessary: - o subvendor and subdevice fields default to PCI_ANY_ID (FFFFFFFF) - o class and classmask fields default to 0 - o driver_data defaults to 0UL. - -Once added, the driver probe routine will be invoked for any unclaimed -PCI devices listed in its (newly updated) pci_ids list. - -When the driver exits, it just calls pci_unregister_driver() and the PCI layer -automatically calls the remove hook for all devices handled by the driver. - - -1.1 "Attributes" for driver functions/data - -Please mark the initialization and cleanup functions where appropriate -(the corresponding macros are defined in ): - - __init Initialization code. Thrown away after the driver - initializes. - __exit Exit code. Ignored for non-modular drivers. - - - __devinit Device initialization code. - Identical to __init if the kernel is not compiled - with CONFIG_HOTPLUG, normal function otherwise. - __devexit The same for __exit. - -Tips on when/where to use the above attributes: - o The module_init()/module_exit() functions (and all - initialization functions called _only_ from these) - should be marked __init/__exit. - - o Do not mark the struct pci_driver. - - o The ID table array should be marked __devinitconst; this is done - automatically if the table is declared with DEFINE_PCI_DEVICE_TABLE(). - - o The probe() and remove() functions should be marked __devinit - and __devexit respectively. All initialization functions - exclusively called by the probe() routine, can be marked __devinit. - Ditto for remove() and __devexit. - - o If mydriver_remove() is marked with __devexit(), then all address - references to mydriver_remove must use __devexit_p(mydriver_remove) - (in the struct pci_driver declaration for example). - __devexit_p() will generate the function name _or_ NULL if the - function will be discarded. For an example, see drivers/net/tg3.c. - - o Do NOT mark a function if you are not sure which mark to use. - Better to not mark the function than mark the function wrong. - - - -2. How to find PCI devices manually -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -PCI drivers should have a really good reason for not using the -pci_register_driver() interface to search for PCI devices. -The main reason PCI devices are controlled by multiple drivers -is because one PCI device implements several different HW services. -E.g. combined serial/parallel port/floppy controller. - -A manual search may be performed using the following constructs: - -Searching by vendor and device ID: - - struct pci_dev *dev = NULL; - while (dev = pci_get_device(VENDOR_ID, DEVICE_ID, dev)) - configure_device(dev); - -Searching by class ID (iterate in a similar way): - - pci_get_class(CLASS_ID, dev) - -Searching by both vendor/device and subsystem vendor/device ID: - - pci_get_subsys(VENDOR_ID,DEVICE_ID, SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev). - -You can use the constant PCI_ANY_ID as a wildcard replacement for -VENDOR_ID or DEVICE_ID. This allows searching for any device from a -specific vendor, for example. - -These functions are hotplug-safe. They increment the reference count on -the pci_dev that they return. You must eventually (possibly at module unload) -decrement the reference count on these devices by calling pci_dev_put(). - - - -3. Device Initialization Steps -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -As noted in the introduction, most PCI drivers need the following steps -for device initialization: - - Enable the device - Request MMIO/IOP resources - Set the DMA mask size (for both coherent and streaming DMA) - Allocate and initialize shared control data (pci_allocate_coherent()) - Access device configuration space (if needed) - Register IRQ handler (request_irq()) - Initialize non-PCI (i.e. LAN/SCSI/etc parts of the chip) - Enable DMA/processing engines. - -The driver can access PCI config space registers at any time. -(Well, almost. When running BIST, config space can go away...but -that will just result in a PCI Bus Master Abort and config reads -will return garbage). - - -3.1 Enable the PCI device -~~~~~~~~~~~~~~~~~~~~~~~~~ -Before touching any device registers, the driver needs to enable -the PCI device by calling pci_enable_device(). This will: - o wake up the device if it was in suspended state, - o allocate I/O and memory regions of the device (if BIOS did not), - o allocate an IRQ (if BIOS did not). - -NOTE: pci_enable_device() can fail! Check the return value. - -[ OS BUG: we don't check resource allocations before enabling those - resources. The sequence would make more sense if we called - pci_request_resources() before calling pci_enable_device(). - Currently, the device drivers can't detect the bug when when two - devices have been allocated the same range. This is not a common - problem and unlikely to get fixed soon. - - This has been discussed before but not changed as of 2.6.19: - http://lkml.org/lkml/2006/3/2/194 -] - -pci_set_master() will enable DMA by setting the bus master bit -in the PCI_COMMAND register. It also fixes the latency timer value if -it's set to something bogus by the BIOS. - -If the PCI device can use the PCI Memory-Write-Invalidate transaction, -call pci_set_mwi(). This enables the PCI_COMMAND bit for Mem-Wr-Inval -and also ensures that the cache line size register is set correctly. -Check the return value of pci_set_mwi() as not all architectures -or chip-sets may support Memory-Write-Invalidate. Alternatively, -if Mem-Wr-Inval would be nice to have but is not required, call -pci_try_set_mwi() to have the system do its best effort at enabling -Mem-Wr-Inval. - - -3.2 Request MMIO/IOP resources -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Memory (MMIO), and I/O port addresses should NOT be read directly -from the PCI device config space. Use the values in the pci_dev structure -as the PCI "bus address" might have been remapped to a "host physical" -address by the arch/chip-set specific kernel support. - -See Documentation/IO-mapping.txt for how to access device registers -or device memory. - -The device driver needs to call pci_request_region() to verify -no other device is already using the same address resource. -Conversely, drivers should call pci_release_region() AFTER -calling pci_disable_device(). -The idea is to prevent two devices colliding on the same address range. - -[ See OS BUG comment above. Currently (2.6.19), The driver can only - determine MMIO and IO Port resource availability _after_ calling - pci_enable_device(). ] - -Generic flavors of pci_request_region() are request_mem_region() -(for MMIO ranges) and request_region() (for IO Port ranges). -Use these for address resources that are not described by "normal" PCI -BARs. - -Also see pci_request_selected_regions() below. - - -3.3 Set the DMA mask size -~~~~~~~~~~~~~~~~~~~~~~~~~ -[ If anything below doesn't make sense, please refer to - Documentation/DMA-API.txt. This section is just a reminder that - drivers need to indicate DMA capabilities of the device and is not - an authoritative source for DMA interfaces. ] - -While all drivers should explicitly indicate the DMA capability -(e.g. 32 or 64 bit) of the PCI bus master, devices with more than -32-bit bus master capability for streaming data need the driver -to "register" this capability by calling pci_set_dma_mask() with -appropriate parameters. In general this allows more efficient DMA -on systems where System RAM exists above 4G _physical_ address. - -Drivers for all PCI-X and PCIe compliant devices must call -pci_set_dma_mask() as they are 64-bit DMA devices. - -Similarly, drivers must also "register" this capability if the device -can directly address "consistent memory" in System RAM above 4G physical -address by calling pci_set_consistent_dma_mask(). -Again, this includes drivers for all PCI-X and PCIe compliant devices. -Many 64-bit "PCI" devices (before PCI-X) and some PCI-X devices are -64-bit DMA capable for payload ("streaming") data but not control -("consistent") data. - - -3.4 Setup shared control data -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Once the DMA masks are set, the driver can allocate "consistent" (a.k.a. shared) -memory. See Documentation/DMA-API.txt for a full description of -the DMA APIs. This section is just a reminder that it needs to be done -before enabling DMA on the device. - - -3.5 Initialize device registers -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Some drivers will need specific "capability" fields programmed -or other "vendor specific" register initialized or reset. -E.g. clearing pending interrupts. - - -3.6 Register IRQ handler -~~~~~~~~~~~~~~~~~~~~~~~~ -While calling request_irq() is the last step described here, -this is often just another intermediate step to initialize a device. -This step can often be deferred until the device is opened for use. - -All interrupt handlers for IRQ lines should be registered with IRQF_SHARED -and use the devid to map IRQs to devices (remember that all PCI IRQ lines -can be shared). - -request_irq() will associate an interrupt handler and device handle -with an interrupt number. Historically interrupt numbers represent -IRQ lines which run from the PCI device to the Interrupt controller. -With MSI and MSI-X (more below) the interrupt number is a CPU "vector". - -request_irq() also enables the interrupt. Make sure the device is -quiesced and does not have any interrupts pending before registering -the interrupt handler. - -MSI and MSI-X are PCI capabilities. Both are "Message Signaled Interrupts" -which deliver interrupts to the CPU via a DMA write to a Local APIC. -The fundamental difference between MSI and MSI-X is how multiple -"vectors" get allocated. MSI requires contiguous blocks of vectors -while MSI-X can allocate several individual ones. - -MSI capability can be enabled by calling pci_enable_msi() or -pci_enable_msix() before calling request_irq(). This causes -the PCI support to program CPU vector data into the PCI device -capability registers. - -If your PCI device supports both, try to enable MSI-X first. -Only one can be enabled at a time. Many architectures, chip-sets, -or BIOSes do NOT support MSI or MSI-X and the call to pci_enable_msi/msix -will fail. This is important to note since many drivers have -two (or more) interrupt handlers: one for MSI/MSI-X and another for IRQs. -They choose which handler to register with request_irq() based on the -return value from pci_enable_msi/msix(). - -There are (at least) two really good reasons for using MSI: -1) MSI is an exclusive interrupt vector by definition. - This means the interrupt handler doesn't have to verify - its device caused the interrupt. - -2) MSI avoids DMA/IRQ race conditions. DMA to host memory is guaranteed - to be visible to the host CPU(s) when the MSI is delivered. This - is important for both data coherency and avoiding stale control data. - This guarantee allows the driver to omit MMIO reads to flush - the DMA stream. - -See drivers/infiniband/hw/mthca/ or drivers/net/tg3.c for examples -of MSI/MSI-X usage. - - - -4. PCI device shutdown -~~~~~~~~~~~~~~~~~~~~~~~ - -When a PCI device driver is being unloaded, most of the following -steps need to be performed: - - Disable the device from generating IRQs - Release the IRQ (free_irq()) - Stop all DMA activity - Release DMA buffers (both streaming and consistent) - Unregister from other subsystems (e.g. scsi or netdev) - Disable device from responding to MMIO/IO Port addresses - Release MMIO/IO Port resource(s) - - -4.1 Stop IRQs on the device -~~~~~~~~~~~~~~~~~~~~~~~~~~~ -How to do this is chip/device specific. If it's not done, it opens -the possibility of a "screaming interrupt" if (and only if) -the IRQ is shared with another device. - -When the shared IRQ handler is "unhooked", the remaining devices -using the same IRQ line will still need the IRQ enabled. Thus if the -"unhooked" device asserts IRQ line, the system will respond assuming -it was one of the remaining devices asserted the IRQ line. Since none -of the other devices will handle the IRQ, the system will "hang" until -it decides the IRQ isn't going to get handled and masks the IRQ (100,000 -iterations later). Once the shared IRQ is masked, the remaining devices -will stop functioning properly. Not a nice situation. - -This is another reason to use MSI or MSI-X if it's available. -MSI and MSI-X are defined to be exclusive interrupts and thus -are not susceptible to the "screaming interrupt" problem. - - -4.2 Release the IRQ -~~~~~~~~~~~~~~~~~~~ -Once the device is quiesced (no more IRQs), one can call free_irq(). -This function will return control once any pending IRQs are handled, -"unhook" the drivers IRQ handler from that IRQ, and finally release -the IRQ if no one else is using it. - - -4.3 Stop all DMA activity -~~~~~~~~~~~~~~~~~~~~~~~~~ -It's extremely important to stop all DMA operations BEFORE attempting -to deallocate DMA control data. Failure to do so can result in memory -corruption, hangs, and on some chip-sets a hard crash. - -Stopping DMA after stopping the IRQs can avoid races where the -IRQ handler might restart DMA engines. - -While this step sounds obvious and trivial, several "mature" drivers -didn't get this step right in the past. - - -4.4 Release DMA buffers -~~~~~~~~~~~~~~~~~~~~~~~ -Once DMA is stopped, clean up streaming DMA first. -I.e. unmap data buffers and return buffers to "upstream" -owners if there is one. - -Then clean up "consistent" buffers which contain the control data. - -See Documentation/DMA-API.txt for details on unmapping interfaces. - - -4.5 Unregister from other subsystems -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Most low level PCI device drivers support some other subsystem -like USB, ALSA, SCSI, NetDev, Infiniband, etc. Make sure your -driver isn't losing resources from that other subsystem. -If this happens, typically the symptom is an Oops (panic) when -the subsystem attempts to call into a driver that has been unloaded. - - -4.6 Disable Device from responding to MMIO/IO Port addresses -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -io_unmap() MMIO or IO Port resources and then call pci_disable_device(). -This is the symmetric opposite of pci_enable_device(). -Do not access device registers after calling pci_disable_device(). - - -4.7 Release MMIO/IO Port Resource(s) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Call pci_release_region() to mark the MMIO or IO Port range as available. -Failure to do so usually results in the inability to reload the driver. - - - -5. How to access PCI config space -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -You can use pci_(read|write)_config_(byte|word|dword) to access the config -space of a device represented by struct pci_dev *. All these functions return 0 -when successful or an error code (PCIBIOS_...) which can be translated to a text -string by pcibios_strerror. Most drivers expect that accesses to valid PCI -devices don't fail. - -If you don't have a struct pci_dev available, you can call -pci_bus_(read|write)_config_(byte|word|dword) to access a given device -and function on that bus. - -If you access fields in the standard portion of the config header, please -use symbolic names of locations and bits declared in . - -If you need to access Extended PCI Capability registers, just call -pci_find_capability() for the particular capability and it will find the -corresponding register block for you. - - - -6. Other interesting functions -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -pci_find_slot() Find pci_dev corresponding to given bus and - slot numbers. -pci_set_power_state() Set PCI Power Management state (0=D0 ... 3=D3) -pci_find_capability() Find specified capability in device's capability - list. -pci_resource_start() Returns bus start address for a given PCI region -pci_resource_end() Returns bus end address for a given PCI region -pci_resource_len() Returns the byte length of a PCI region -pci_set_drvdata() Set private driver data pointer for a pci_dev -pci_get_drvdata() Return private driver data pointer for a pci_dev -pci_set_mwi() Enable Memory-Write-Invalidate transactions. -pci_clear_mwi() Disable Memory-Write-Invalidate transactions. - - - -7. Miscellaneous hints -~~~~~~~~~~~~~~~~~~~~~~ - -When displaying PCI device names to the user (for example when a driver wants -to tell the user what card has it found), please use pci_name(pci_dev). - -Always refer to the PCI devices by a pointer to the pci_dev structure. -All PCI layer functions use this identification and it's the only -reasonable one. Don't use bus/slot/function numbers except for very -special purposes -- on systems with multiple primary buses their semantics -can be pretty complex. - -Don't try to turn on Fast Back to Back writes in your driver. All devices -on the bus need to be capable of doing it, so this is something which needs -to be handled by platform and generic code, not individual drivers. - - - -8. Vendor and device identifications -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -One is not not required to add new device ids to include/linux/pci_ids.h. -Please add PCI_VENDOR_ID_xxx for vendors and a hex constant for device ids. - -PCI_VENDOR_ID_xxx constants are re-used. The device ids are arbitrary -hex numbers (vendor controlled) and normally used only in a single -location, the pci_device_id table. - -Please DO submit new vendor/device ids to pciids.sourceforge.net project. - - - -9. Obsolete functions -~~~~~~~~~~~~~~~~~~~~~ - -There are several functions which you might come across when trying to -port an old driver to the new PCI interface. They are no longer present -in the kernel as they aren't compatible with hotplug or PCI domains or -having sane locking. - -pci_find_device() Superseded by pci_get_device() -pci_find_subsys() Superseded by pci_get_subsys() -pci_find_slot() Superseded by pci_get_slot() - - -The alternative is the traditional PCI device driver that walks PCI -device lists. This is still possible but discouraged. - - - -10. MMIO Space and "Write Posting" -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Converting a driver from using I/O Port space to using MMIO space -often requires some additional changes. Specifically, "write posting" -needs to be handled. Many drivers (e.g. tg3, acenic, sym53c8xx_2) -already do this. I/O Port space guarantees write transactions reach the PCI -device before the CPU can continue. Writes to MMIO space allow the CPU -to continue before the transaction reaches the PCI device. HW weenies -call this "Write Posting" because the write completion is "posted" to -the CPU before the transaction has reached its destination. - -Thus, timing sensitive code should add readl() where the CPU is -expected to wait before doing other work. The classic "bit banging" -sequence works fine for I/O Port space: - - for (i = 8; --i; val >>= 1) { - outb(val & 1, ioport_reg); /* write bit */ - udelay(10); - } - -The same sequence for MMIO space should be: - - for (i = 8; --i; val >>= 1) { - writeb(val & 1, mmio_reg); /* write bit */ - readb(safe_mmio_reg); /* flush posted write */ - udelay(10); - } - -It is important that "safe_mmio_reg" not have any side effects that -interferes with the correct operation of the device. - -Another case to watch out for is when resetting a PCI device. Use PCI -Configuration space reads to flush the writel(). This will gracefully -handle the PCI master abort on all platforms if the PCI device is -expected to not respond to a readl(). Most x86 platforms will allow -MMIO reads to master abort (a.k.a. "Soft Fail") and return garbage -(e.g. ~0). But many RISC platforms will crash (a.k.a."Hard Fail"). - diff --git a/Documentation/pcieaer-howto.txt b/Documentation/pcieaer-howto.txt deleted file mode 100644 index d5da86170106..000000000000 --- a/Documentation/pcieaer-howto.txt +++ /dev/null @@ -1,253 +0,0 @@ - The PCI Express Advanced Error Reporting Driver Guide HOWTO - T. Long Nguyen - Yanmin Zhang - 07/29/2006 - - -1. Overview - -1.1 About this guide - -This guide describes the basics of the PCI Express Advanced Error -Reporting (AER) driver and provides information on how to use it, as -well as how to enable the drivers of endpoint devices to conform with -PCI Express AER driver. - -1.2 Copyright © Intel Corporation 2006. - -1.3 What is the PCI Express AER Driver? - -PCI Express error signaling can occur on the PCI Express link itself -or on behalf of transactions initiated on the link. PCI Express -defines two error reporting paradigms: the baseline capability and -the Advanced Error Reporting capability. The baseline capability is -required of all PCI Express components providing a minimum defined -set of error reporting requirements. Advanced Error Reporting -capability is implemented with a PCI Express advanced error reporting -extended capability structure providing more robust error reporting. - -The PCI Express AER driver provides the infrastructure to support PCI -Express Advanced Error Reporting capability. The PCI Express AER -driver provides three basic functions: - -- Gathers the comprehensive error information if errors occurred. -- Reports error to the users. -- Performs error recovery actions. - -AER driver only attaches root ports which support PCI-Express AER -capability. - - -2. User Guide - -2.1 Include the PCI Express AER Root Driver into the Linux Kernel - -The PCI Express AER Root driver is a Root Port service driver attached -to the PCI Express Port Bus driver. If a user wants to use it, the driver -has to be compiled. Option CONFIG_PCIEAER supports this capability. It -depends on CONFIG_PCIEPORTBUS, so pls. set CONFIG_PCIEPORTBUS=y and -CONFIG_PCIEAER = y. - -2.2 Load PCI Express AER Root Driver -There is a case where a system has AER support in BIOS. Enabling the AER -Root driver and having AER support in BIOS may result unpredictable -behavior. To avoid this conflict, a successful load of the AER Root driver -requires ACPI _OSC support in the BIOS to allow the AER Root driver to -request for native control of AER. See the PCI FW 3.0 Specification for -details regarding OSC usage. Currently, lots of firmwares don't provide -_OSC support while they use PCI Express. To support such firmwares, -forceload, a parameter of type bool, could enable AER to continue to -be initiated although firmwares have no _OSC support. To enable the -walkaround, pls. add aerdriver.forceload=y to kernel boot parameter line -when booting kernel. Note that forceload=n by default. - -2.3 AER error output -When a PCI-E AER error is captured, an error message will be outputed to -console. If it's a correctable error, it is outputed as a warning. -Otherwise, it is printed as an error. So users could choose different -log level to filter out correctable error messages. - -Below shows an example. -+------ PCI-Express Device Error -----+ -Error Severity : Uncorrected (Fatal) -PCIE Bus Error type : Transaction Layer -Unsupported Request : First -Requester ID : 0500 -VendorID=8086h, DeviceID=0329h, Bus=05h, Device=00h, Function=00h -TLB Header: -04000001 00200a03 05010000 00050100 - -In the example, 'Requester ID' means the ID of the device who sends -the error message to root port. Pls. refer to pci express specs for -other fields. - - -3. Developer Guide - -To enable AER aware support requires a software driver to configure -the AER capability structure within its device and to provide callbacks. - -To support AER better, developers need understand how AER does work -firstly. - -PCI Express errors are classified into two types: correctable errors -and uncorrectable errors. This classification is based on the impacts -of those errors, which may result in degraded performance or function -failure. - -Correctable errors pose no impacts on the functionality of the -interface. The PCI Express protocol can recover without any software -intervention or any loss of data. These errors are detected and -corrected by hardware. Unlike correctable errors, uncorrectable -errors impact functionality of the interface. Uncorrectable errors -can cause a particular transaction or a particular PCI Express link -to be unreliable. Depending on those error conditions, uncorrectable -errors are further classified into non-fatal errors and fatal errors. -Non-fatal errors cause the particular transaction to be unreliable, -but the PCI Express link itself is fully functional. Fatal errors, on -the other hand, cause the link to be unreliable. - -When AER is enabled, a PCI Express device will automatically send an -error message to the PCIE root port above it when the device captures -an error. The Root Port, upon receiving an error reporting message, -internally processes and logs the error message in its PCI Express -capability structure. Error information being logged includes storing -the error reporting agent's requestor ID into the Error Source -Identification Registers and setting the error bits of the Root Error -Status Register accordingly. If AER error reporting is enabled in Root -Error Command Register, the Root Port generates an interrupt if an -error is detected. - -Note that the errors as described above are related to the PCI Express -hierarchy and links. These errors do not include any device specific -errors because device specific errors will still get sent directly to -the device driver. - -3.1 Configure the AER capability structure - -AER aware drivers of PCI Express component need change the device -control registers to enable AER. They also could change AER registers, -including mask and severity registers. Helper function -pci_enable_pcie_error_reporting could be used to enable AER. See -section 3.3. - -3.2. Provide callbacks - -3.2.1 callback reset_link to reset pci express link - -This callback is used to reset the pci express physical link when a -fatal error happens. The root port aer service driver provides a -default reset_link function, but different upstream ports might -have different specifications to reset pci express link, so all -upstream ports should provide their own reset_link functions. - -In struct pcie_port_service_driver, a new pointer, reset_link, is -added. - -pci_ers_result_t (*reset_link) (struct pci_dev *dev); - -Section 3.2.2.2 provides more detailed info on when to call -reset_link. - -3.2.2 PCI error-recovery callbacks - -The PCI Express AER Root driver uses error callbacks to coordinate -with downstream device drivers associated with a hierarchy in question -when performing error recovery actions. - -Data struct pci_driver has a pointer, err_handler, to point to -pci_error_handlers who consists of a couple of callback function -pointers. AER driver follows the rules defined in -pci-error-recovery.txt except pci express specific parts (e.g. -reset_link). Pls. refer to pci-error-recovery.txt for detailed -definitions of the callbacks. - -Below sections specify when to call the error callback functions. - -3.2.2.1 Correctable errors - -Correctable errors pose no impacts on the functionality of -the interface. The PCI Express protocol can recover without any -software intervention or any loss of data. These errors do not -require any recovery actions. The AER driver clears the device's -correctable error status register accordingly and logs these errors. - -3.2.2.2 Non-correctable (non-fatal and fatal) errors - -If an error message indicates a non-fatal error, performing link reset -at upstream is not required. The AER driver calls error_detected(dev, -pci_channel_io_normal) to all drivers associated within a hierarchy in -question. for example, -EndPoint<==>DownstreamPort B<==>UpstreamPort A<==>RootPort. -If Upstream port A captures an AER error, the hierarchy consists of -Downstream port B and EndPoint. - -A driver may return PCI_ERS_RESULT_CAN_RECOVER, -PCI_ERS_RESULT_DISCONNECT, or PCI_ERS_RESULT_NEED_RESET, depending on -whether it can recover or the AER driver calls mmio_enabled as next. - -If an error message indicates a fatal error, kernel will broadcast -error_detected(dev, pci_channel_io_frozen) to all drivers within -a hierarchy in question. Then, performing link reset at upstream is -necessary. As different kinds of devices might use different approaches -to reset link, AER port service driver is required to provide the -function to reset link. Firstly, kernel looks for if the upstream -component has an aer driver. If it has, kernel uses the reset_link -callback of the aer driver. If the upstream component has no aer driver -and the port is downstream port, we will use the aer driver of the -root port who reports the AER error. As for upstream ports, -they should provide their own aer service drivers with reset_link -function. If error_detected returns PCI_ERS_RESULT_CAN_RECOVER and -reset_link returns PCI_ERS_RESULT_RECOVERED, the error handling goes -to mmio_enabled. - -3.3 helper functions - -3.3.1 int pci_find_aer_capability(struct pci_dev *dev); -pci_find_aer_capability locates the PCI Express AER capability -in the device configuration space. If the device doesn't support -PCI-Express AER, the function returns 0. - -3.3.2 int pci_enable_pcie_error_reporting(struct pci_dev *dev); -pci_enable_pcie_error_reporting enables the device to send error -messages to root port when an error is detected. Note that devices -don't enable the error reporting by default, so device drivers need -call this function to enable it. - -3.3.3 int pci_disable_pcie_error_reporting(struct pci_dev *dev); -pci_disable_pcie_error_reporting disables the device to send error -messages to root port when an error is detected. - -3.3.4 int pci_cleanup_aer_uncorrect_error_status(struct pci_dev *dev); -pci_cleanup_aer_uncorrect_error_status cleanups the uncorrectable -error status register. - -3.4 Frequent Asked Questions - -Q: What happens if a PCI Express device driver does not provide an -error recovery handler (pci_driver->err_handler is equal to NULL)? - -A: The devices attached with the driver won't be recovered. If the -error is fatal, kernel will print out warning messages. Please refer -to section 3 for more information. - -Q: What happens if an upstream port service driver does not provide -callback reset_link? - -A: Fatal error recovery will fail if the errors are reported by the -upstream ports who are attached by the service driver. - -Q: How does this infrastructure deal with driver that is not PCI -Express aware? - -A: This infrastructure calls the error callback functions of the -driver when an error happens. But if the driver is not aware of -PCI Express, the device might not report its own errors to root -port. - -Q: What modifications will that driver need to make it compatible -with the PCI Express AER Root driver? - -A: It could call the helper functions to enable AER in devices and -cleanup uncorrectable status register. Pls. refer to section 3.3. - -- cgit v1.2.3 From 1ba6ab11d8fbd8d29afec4e39236e1255ae0339a Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Wed, 13 Feb 2008 15:06:38 -0800 Subject: PCI: remove initial bios sort of PCI devices on x86 We currently keep 2 lists of PCI devices in the system, one in the driver core, and one all on its own. This second list is sorted at boot time, in "BIOS" order, to try to remain compatible with older kernels (2.2 and earlier days). There was also a "nosort" option to turn this sorting off, to remain compatible with even older kernel versions, but that just ends up being what we have been doing from 2.5 days... Unfortunately, the second list of devices is not really ever used to determine the probing order of PCI devices or drivers[1]. That is done using the driver core list instead. This change happened back in the early 2.5 days. Relying on BIOS ording for the binding of drivers to specific device names is problematic for many reasons, and userspace tools like udev exist to properly name devices in a persistant manner if that is needed, no reliance on the BIOS is needed. Matt Domsch and others at Dell noticed this back in 2006, and added a boot option to sort the PCI device lists (both of them) in a breadth-first manner to help remain compatible with the 2.4 order, if needed for any reason. This option is not going away, as some systems rely on them. This patch removes the sorting of the internal PCI device list in "BIOS" mode, as it's not needed at all anymore, and hasn't for many years. I've also removed the PCI flags for this from some other arches that for some reason defined them, but never used them. This should not change the ordering of any drivers or device probing. [1] The old-style pci_get_device and pci_find_device() still used this sorting order, but there are very few drivers that use these functions, as they are deprecated for use in this manner. If for some reason, a driver rely on the order and uses these functions, the breadth-first boot option will resolve any problem. Cc: Matt Domsch Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 4 -- arch/frv/mb93090-mb00/pci-frv.h | 2 - arch/mn10300/unit-asb2305/pci-asb2305.h | 2 - arch/sh/drivers/pci/pci-sh4.h | 2 - arch/x86/pci/common.c | 7 ---- arch/x86/pci/pcbios.c | 72 --------------------------------- arch/x86/pci/pci.h | 3 -- include/asm-sh/mpc1211/pci.h | 2 - 8 files changed, 94 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index 4b0f1ae31a4c..e30d8fe4e4b1 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -1461,10 +1461,6 @@ and is between 256 and 4096 characters. It is defined in the file nomsi [MSI] If the PCI_MSI kernel config parameter is enabled, this kernel boot option can be used to disable the use of MSI interrupts system-wide. - nosort [X86-32] Don't sort PCI devices according to - order given by the PCI BIOS. This sorting is - done to get a device order compatible with - older kernels. biosirq [X86-32] Use PCI BIOS calls to get the interrupt routing table. These calls are known to be buggy on several machines and they hang the machine diff --git a/arch/frv/mb93090-mb00/pci-frv.h b/arch/frv/mb93090-mb00/pci-frv.h index 7481797ab382..0c7bf39dc729 100644 --- a/arch/frv/mb93090-mb00/pci-frv.h +++ b/arch/frv/mb93090-mb00/pci-frv.h @@ -17,8 +17,6 @@ #define PCI_PROBE_BIOS 0x0001 #define PCI_PROBE_CONF1 0x0002 #define PCI_PROBE_CONF2 0x0004 -#define PCI_NO_SORT 0x0100 -#define PCI_BIOS_SORT 0x0200 #define PCI_NO_CHECKS 0x0400 #define PCI_ASSIGN_ROMS 0x1000 #define PCI_BIOS_IRQ_SCAN 0x2000 diff --git a/arch/mn10300/unit-asb2305/pci-asb2305.h b/arch/mn10300/unit-asb2305/pci-asb2305.h index 84634fa3bce6..9763d1ce343a 100644 --- a/arch/mn10300/unit-asb2305/pci-asb2305.h +++ b/arch/mn10300/unit-asb2305/pci-asb2305.h @@ -23,8 +23,6 @@ #define PCI_PROBE_BIOS 1 #define PCI_PROBE_CONF1 2 #define PCI_PROBE_CONF2 4 -#define PCI_NO_SORT 0x100 -#define PCI_BIOS_SORT 0x200 #define PCI_NO_CHECKS 0x400 #define PCI_ASSIGN_ROMS 0x1000 #define PCI_BIOS_IRQ_SCAN 0x2000 diff --git a/arch/sh/drivers/pci/pci-sh4.h b/arch/sh/drivers/pci/pci-sh4.h index 07e29506080f..a83dcf70c13b 100644 --- a/arch/sh/drivers/pci/pci-sh4.h +++ b/arch/sh/drivers/pci/pci-sh4.h @@ -15,8 +15,6 @@ #define PCI_PROBE_BIOS 1 #define PCI_PROBE_CONF1 2 #define PCI_PROBE_CONF2 4 -#define PCI_NO_SORT 0x100 -#define PCI_BIOS_SORT 0x200 #define PCI_NO_CHECKS 0x400 #define PCI_ASSIGN_ROMS 0x1000 #define PCI_BIOS_IRQ_SCAN 0x2000 diff --git a/arch/x86/pci/common.c b/arch/x86/pci/common.c index 7b6e3bb9b28c..c9ff4ff66739 100644 --- a/arch/x86/pci/common.c +++ b/arch/x86/pci/common.c @@ -427,10 +427,6 @@ static int __init pcibios_init(void) if (pci_bf_sort >= pci_force_bf) pci_sort_breadthfirst(); -#ifdef CONFIG_PCI_BIOS - if ((pci_probe & PCI_BIOS_SORT) && !(pci_probe & PCI_NO_SORT)) - pcibios_sort(); -#endif return 0; } @@ -455,9 +451,6 @@ char * __devinit pcibios_setup(char *str) } else if (!strcmp(str, "nobios")) { pci_probe &= ~PCI_PROBE_BIOS; return NULL; - } else if (!strcmp(str, "nosort")) { - pci_probe |= PCI_NO_SORT; - return NULL; } else if (!strcmp(str, "biosirq")) { pci_probe |= PCI_BIOS_IRQ_SCAN; return NULL; diff --git a/arch/x86/pci/pcbios.c b/arch/x86/pci/pcbios.c index 2f7109ac4c15..37472fc6f729 100644 --- a/arch/x86/pci/pcbios.c +++ b/arch/x86/pci/pcbios.c @@ -152,28 +152,6 @@ static int __devinit check_pcibios(void) return 0; } -static int __devinit pci_bios_find_device (unsigned short vendor, unsigned short device_id, - unsigned short index, unsigned char *bus, unsigned char *device_fn) -{ - unsigned short bx; - unsigned short ret; - - __asm__("lcall *(%%edi); cld\n\t" - "jc 1f\n\t" - "xor %%ah, %%ah\n" - "1:" - : "=b" (bx), - "=a" (ret) - : "1" (PCIBIOS_FIND_PCI_DEVICE), - "c" (device_id), - "d" (vendor), - "S" ((int) index), - "D" (&pci_indirect)); - *bus = (bx >> 8) & 0xff; - *device_fn = bx & 0xff; - return (int) (ret & 0xff00) >> 8; -} - static int pci_bios_read(unsigned int seg, unsigned int bus, unsigned int devfn, int reg, int len, u32 *value) { @@ -363,55 +341,6 @@ static struct pci_raw_ops * __devinit pci_find_bios(void) return NULL; } -/* - * Sort the device list according to PCI BIOS. Nasty hack, but since some - * fool forgot to define the `correct' device order in the PCI BIOS specs - * and we want to be (possibly bug-to-bug ;-]) compatible with older kernels - * which used BIOS ordering, we are bound to do this... - */ - -void __devinit pcibios_sort(void) -{ - LIST_HEAD(sorted_devices); - struct list_head *ln; - struct pci_dev *dev, *d; - int idx, found; - unsigned char bus, devfn; - - DBG("PCI: Sorting device list...\n"); - while (!list_empty(&pci_devices)) { - ln = pci_devices.next; - dev = pci_dev_g(ln); - idx = found = 0; - while (pci_bios_find_device(dev->vendor, dev->device, idx, &bus, &devfn) == PCIBIOS_SUCCESSFUL) { - idx++; - list_for_each(ln, &pci_devices) { - d = pci_dev_g(ln); - if (d->bus->number == bus && d->devfn == devfn) { - list_move_tail(&d->global_list, &sorted_devices); - if (d == dev) - found = 1; - break; - } - } - if (ln == &pci_devices) { - printk(KERN_WARNING "PCI: BIOS reporting unknown device %02x:%02x\n", bus, devfn); - /* - * We must not continue scanning as several buggy BIOSes - * return garbage after the last device. Grr. - */ - break; - } - } - if (!found) { - printk(KERN_WARNING "PCI: Device %s not found by BIOS\n", - pci_name(dev)); - list_move_tail(&dev->global_list, &sorted_devices); - } - } - list_splice(&sorted_devices, &pci_devices); -} - /* * BIOS Functions for IRQ Routing */ @@ -495,7 +424,6 @@ void __init pci_pcbios_init(void) { if ((pci_probe & PCI_PROBE_BIOS) && ((raw_pci_ops = pci_find_bios()))) { - pci_probe |= PCI_BIOS_SORT; pci_bios_present = 1; } } diff --git a/arch/x86/pci/pci.h b/arch/x86/pci/pci.h index 3431518d921a..02b016a98423 100644 --- a/arch/x86/pci/pci.h +++ b/arch/x86/pci/pci.h @@ -19,8 +19,6 @@ #define PCI_PROBE_MASK 0x000f #define PCI_PROBE_NOEARLY 0x0010 -#define PCI_NO_SORT 0x0100 -#define PCI_BIOS_SORT 0x0200 #define PCI_NO_CHECKS 0x0400 #define PCI_USE_PIRQ_MASK 0x0800 #define PCI_ASSIGN_ROMS 0x1000 @@ -101,7 +99,6 @@ extern int pci_direct_probe(void); extern void pci_direct_init(int type); extern void pci_pcbios_init(void); extern void pci_mmcfg_init(int type); -extern void pcibios_sort(void); /* pci-mmconfig.c */ diff --git a/include/asm-sh/mpc1211/pci.h b/include/asm-sh/mpc1211/pci.h index 5d3712c3a701..d9162c5ed76a 100644 --- a/include/asm-sh/mpc1211/pci.h +++ b/include/asm-sh/mpc1211/pci.h @@ -24,8 +24,6 @@ #define PCI_PROBE_BIOS 1 #define PCI_PROBE_CONF1 2 #define PCI_PROBE_CONF2 4 -#define PCI_NO_SORT 0x100 -#define PCI_BIOS_SORT 0x200 #define PCI_NO_CHECKS 0x400 #define PCI_ASSIGN_ROMS 0x1000 #define PCI_BIOS_IRQ_SCAN 0x2000 -- cgit v1.2.3 From 5e0d2a6fc094a9b5047998deefeb1254c66856ee Mon Sep 17 00:00:00 2001 From: mark gross Date: Tue, 4 Mar 2008 15:22:08 -0800 Subject: PCI: iommu: iotlb flushing This patch is for batching up the flushing of the IOTLB for the DMAR implementation found in the Intel VT-d hardware. It works by building a list of to be flushed IOTLB entries and a bitmap list of which DMAR engine they are from. After either a high water mark (250 accessible via debugfs) or 10ms the list of iova's will be reclaimed and the DMAR engines associated are IOTLB-flushed. This approach recovers 15 to 20% of the performance lost when using the IOMMU for my netperf udp stream benchmark with small packets. It can be disabled with a kernel boot parameter "intel_iommu=strict". Its use does weaken the IOMMU protections a bit. Signed-off-by: Mark Gross Signed-off-by: Andrew Morton Signed-off-by: Greg Kroah-Hartman --- Documentation/kernel-parameters.txt | 4 + drivers/pci/intel-iommu.c | 147 +++++++++++++++++++++++++++++++----- drivers/pci/iova.h | 2 + 3 files changed, 135 insertions(+), 18 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index e30d8fe4e4b1..f7492cd10093 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -847,6 +847,10 @@ and is between 256 and 4096 characters. It is defined in the file than 32 bit addressing. The default is to look for translation below 32 bit and if not available then look in the higher range. + strict [Default Off] + With this option on every unmap_single operation will + result in a hardware IOTLB flush operation as opposed + to batching them for performance. io_delay= [X86-32,X86-64] I/O delay method 0x80 diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 4cb949f0ebd9..8690a0d45d7f 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c @@ -22,6 +22,7 @@ #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #include #include #include +#include #include "iova.h" #include "intel-iommu.h" #include /* force_iommu in this header in x86-64*/ @@ -51,11 +53,32 @@ #define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) + +static void flush_unmaps_timeout(unsigned long data); + +DEFINE_TIMER(unmap_timer, flush_unmaps_timeout, 0, 0); + +static struct intel_iommu *g_iommus; +/* bitmap for indexing intel_iommus */ +static unsigned long *g_iommus_to_flush; +static int g_num_of_iommus; + +static DEFINE_SPINLOCK(async_umap_flush_lock); +static LIST_HEAD(unmaps_to_do); + +static int timer_on; +static long list_size; +static int high_watermark; + +static struct dentry *intel_iommu_debug, *debug; + + static void domain_remove_dev_info(struct dmar_domain *domain); static int dmar_disabled; static int __initdata dmar_map_gfx = 1; static int dmar_forcedac; +static int intel_iommu_strict; #define DUMMY_DEVICE_DOMAIN_INFO ((struct device_domain_info *)(-1)) static DEFINE_SPINLOCK(device_domain_lock); @@ -74,9 +97,13 @@ static int __init intel_iommu_setup(char *str) printk(KERN_INFO "Intel-IOMMU: disable GFX device mapping\n"); } else if (!strncmp(str, "forcedac", 8)) { - printk (KERN_INFO + printk(KERN_INFO "Intel-IOMMU: Forcing DAC for PCI devices\n"); dmar_forcedac = 1; + } else if (!strncmp(str, "strict", 6)) { + printk(KERN_INFO + "Intel-IOMMU: disable batched IOTLB flush\n"); + intel_iommu_strict = 1; } str += strcspn(str, ","); @@ -966,17 +993,13 @@ static int iommu_init_domains(struct intel_iommu *iommu) set_bit(0, iommu->domain_ids); return 0; } - -static struct intel_iommu *alloc_iommu(struct dmar_drhd_unit *drhd) +static struct intel_iommu *alloc_iommu(struct intel_iommu *iommu, + struct dmar_drhd_unit *drhd) { - struct intel_iommu *iommu; int ret; int map_size; u32 ver; - iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); - if (!iommu) - return NULL; iommu->reg = ioremap(drhd->reg_base_addr, PAGE_SIZE_4K); if (!iommu->reg) { printk(KERN_ERR "IOMMU: can't map the region\n"); @@ -1404,7 +1427,7 @@ static int dmar_pci_device_match(struct pci_dev *devices[], int cnt, int index; while (dev) { - for (index = 0; index < cnt; index ++) + for (index = 0; index < cnt; index++) if (dev == devices[index]) return 1; @@ -1669,7 +1692,7 @@ int __init init_dmars(void) struct dmar_rmrr_unit *rmrr; struct pci_dev *pdev; struct intel_iommu *iommu; - int ret, unit = 0; + int nlongs, i, ret, unit = 0; /* * for each drhd @@ -1680,7 +1703,35 @@ int __init init_dmars(void) for_each_drhd_unit(drhd) { if (drhd->ignored) continue; - iommu = alloc_iommu(drhd); + g_num_of_iommus++; + /* + * lock not needed as this is only incremented in the single + * threaded kernel __init code path all other access are read + * only + */ + } + + nlongs = BITS_TO_LONGS(g_num_of_iommus); + g_iommus_to_flush = kzalloc(nlongs * sizeof(unsigned long), GFP_KERNEL); + if (!g_iommus_to_flush) { + printk(KERN_ERR "Intel-IOMMU: " + "Allocating bitmap array failed\n"); + return -ENOMEM; + } + + g_iommus = kzalloc(g_num_of_iommus * sizeof(*iommu), GFP_KERNEL); + if (!g_iommus) { + kfree(g_iommus_to_flush); + ret = -ENOMEM; + goto error; + } + + i = 0; + for_each_drhd_unit(drhd) { + if (drhd->ignored) + continue; + iommu = alloc_iommu(&g_iommus[i], drhd); + i++; if (!iommu) { ret = -ENOMEM; goto error; @@ -1713,7 +1764,6 @@ int __init init_dmars(void) * endfor */ for_each_rmrr_units(rmrr) { - int i; for (i = 0; i < rmrr->devices_cnt; i++) { pdev = rmrr->devices[i]; /* some BIOS lists non-exist devices in DMAR table */ @@ -1769,6 +1819,7 @@ error: iommu = drhd->iommu; free_iommu(iommu); } + kfree(g_iommus); return ret; } @@ -1917,6 +1968,53 @@ error: return 0; } +static void flush_unmaps(void) +{ + struct iova *node, *n; + unsigned long flags; + int i; + + spin_lock_irqsave(&async_umap_flush_lock, flags); + timer_on = 0; + + /* just flush them all */ + for (i = 0; i < g_num_of_iommus; i++) { + if (test_and_clear_bit(i, g_iommus_to_flush)) + iommu_flush_iotlb_global(&g_iommus[i], 0); + } + + list_for_each_entry_safe(node, n, &unmaps_to_do, list) { + /* free iova */ + list_del(&node->list); + __free_iova(&((struct dmar_domain *)node->dmar)->iovad, node); + + } + list_size = 0; + spin_unlock_irqrestore(&async_umap_flush_lock, flags); +} + +static void flush_unmaps_timeout(unsigned long data) +{ + flush_unmaps(); +} + +static void add_unmap(struct dmar_domain *dom, struct iova *iova) +{ + unsigned long flags; + + spin_lock_irqsave(&async_umap_flush_lock, flags); + iova->dmar = dom; + list_add(&iova->list, &unmaps_to_do); + set_bit((dom->iommu - g_iommus), g_iommus_to_flush); + + if (!timer_on) { + mod_timer(&unmap_timer, jiffies + msecs_to_jiffies(10)); + timer_on = 1; + } + list_size++; + spin_unlock_irqrestore(&async_umap_flush_lock, flags); +} + static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size, int dir) { @@ -1944,13 +2042,21 @@ static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, dma_pte_clear_range(domain, start_addr, start_addr + size); /* free page tables */ dma_pte_free_pagetable(domain, start_addr, start_addr + size); - - if (iommu_flush_iotlb_psi(domain->iommu, domain->id, start_addr, - size >> PAGE_SHIFT_4K, 0)) - iommu_flush_write_buffer(domain->iommu); - - /* free iova */ - __free_iova(&domain->iovad, iova); + if (intel_iommu_strict) { + if (iommu_flush_iotlb_psi(domain->iommu, + domain->id, start_addr, size >> PAGE_SHIFT_4K, 0)) + iommu_flush_write_buffer(domain->iommu); + /* free iova */ + __free_iova(&domain->iovad, iova); + } else { + add_unmap(domain, iova); + /* + * queue up the release of the unmap to save the 1/6th of the + * cpu used up by the iotlb flush operation... + */ + if (list_size > high_watermark) + flush_unmaps(); + } } static void * intel_alloc_coherent(struct device *hwdev, size_t size, @@ -2274,6 +2380,10 @@ int __init intel_iommu_init(void) if (dmar_table_init()) return -ENODEV; + high_watermark = 250; + intel_iommu_debug = debugfs_create_dir("intel_iommu", NULL); + debug = debugfs_create_u32("high_watermark", S_IWUGO | S_IRUGO, + intel_iommu_debug, &high_watermark); iommu_init_mempool(); dmar_init_reserved_ranges(); @@ -2289,6 +2399,7 @@ int __init intel_iommu_init(void) printk(KERN_INFO "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n"); + init_timer(&unmap_timer); force_iommu = 1; dma_ops = &intel_dma_ops; return 0; diff --git a/drivers/pci/iova.h b/drivers/pci/iova.h index 228f6c94b69c..2f1317801b20 100644 --- a/drivers/pci/iova.h +++ b/drivers/pci/iova.h @@ -24,6 +24,8 @@ struct iova { struct rb_node node; unsigned long pfn_hi; /* IOMMU dish out addr hi */ unsigned long pfn_lo; /* IOMMU dish out addr lo */ + struct list_head list; + void *dmar; }; /* holds all the iova translations for a domain */ -- cgit v1.2.3 From 94e6108803469a37ee1e3c92dafdd1d59298602f Mon Sep 17 00:00:00 2001 From: Ben Hutchings Date: Wed, 5 Mar 2008 16:52:39 +0000 Subject: PCI: Expose PCI VPD through sysfs Vital Product Data (VPD) may be exposed by PCI devices in several ways. It is generally unsafe to read this information through the existing interfaces to user-land because of stateful interfaces. This adds: - abstract operations for VPD access (struct pci_vpd_ops) - VPD state information in struct pci_dev (struct pci_vpd) - an implementation of the VPD access method specified in PCI 2.2 (in access.c) - a 'vpd' binary file in sysfs directories for PCI devices with VPD operations defined It adds a probe for PCI 2.2 VPD in pci_scan_device() and release of VPD state in pci_release_dev(). Signed-off-by: Ben Hutchings Signed-off-by: Greg Kroah-Hartman --- Documentation/ABI/testing/sysfs-bus-pci | 11 +++ drivers/pci/access.c | 166 ++++++++++++++++++++++++++++++++ drivers/pci/pci-sysfs.c | 109 ++++++++++++++++++--- drivers/pci/pci.h | 19 ++++ drivers/pci/probe.c | 3 + include/linux/pci.h | 3 + 6 files changed, 297 insertions(+), 14 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-bus-pci (limited to 'Documentation') diff --git a/Documentation/ABI/testing/sysfs-bus-pci b/Documentation/ABI/testing/sysfs-bus-pci new file mode 100644 index 000000000000..ceddcff4082a --- /dev/null +++ b/Documentation/ABI/testing/sysfs-bus-pci @@ -0,0 +1,11 @@ +What: /sys/bus/pci/devices/.../vpd +Date: February 2008 +Contact: Ben Hutchings +Description: + A file named vpd in a device directory will be a + binary file containing the Vital Product Data for the + device. It should follow the VPD format defined in + PCI Specification 2.1 or 2.2, but users should consider + that some devices may have malformatted data. If the + underlying VPD has a writable section then the + corresponding section of this file will be writable. diff --git a/drivers/pci/access.c b/drivers/pci/access.c index fc405f0165d9..ec8f7002b09d 100644 --- a/drivers/pci/access.c +++ b/drivers/pci/access.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -126,6 +127,171 @@ PCI_USER_WRITE_CONFIG(byte, u8) PCI_USER_WRITE_CONFIG(word, u16) PCI_USER_WRITE_CONFIG(dword, u32) +/* VPD access through PCI 2.2+ VPD capability */ + +#define PCI_VPD_PCI22_SIZE (PCI_VPD_ADDR_MASK + 1) + +struct pci_vpd_pci22 { + struct pci_vpd base; + spinlock_t lock; /* controls access to hardware and the flags */ + u8 cap; + bool busy; + bool flag; /* value of F bit to wait for */ +}; + +/* Wait for last operation to complete */ +static int pci_vpd_pci22_wait(struct pci_dev *dev) +{ + struct pci_vpd_pci22 *vpd = + container_of(dev->vpd, struct pci_vpd_pci22, base); + u16 flag, status; + int wait; + int ret; + + if (!vpd->busy) + return 0; + + flag = vpd->flag ? PCI_VPD_ADDR_F : 0; + wait = vpd->flag ? 10 : 1000; /* read: 100 us; write: 10 ms */ + for (;;) { + ret = pci_user_read_config_word(dev, + vpd->cap + PCI_VPD_ADDR, + &status); + if (ret < 0) + return ret; + if ((status & PCI_VPD_ADDR_F) == flag) { + vpd->busy = false; + return 0; + } + if (wait-- == 0) + return -ETIMEDOUT; + udelay(10); + } +} + +static int pci_vpd_pci22_read(struct pci_dev *dev, int pos, int size, + char *buf) +{ + struct pci_vpd_pci22 *vpd = + container_of(dev->vpd, struct pci_vpd_pci22, base); + u32 val; + int ret; + int begin, end, i; + + if (pos < 0 || pos > PCI_VPD_PCI22_SIZE || + size > PCI_VPD_PCI22_SIZE - pos) + return -EINVAL; + if (size == 0) + return 0; + + spin_lock_irq(&vpd->lock); + ret = pci_vpd_pci22_wait(dev); + if (ret < 0) + goto out; + ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR, + pos & ~3); + if (ret < 0) + goto out; + vpd->busy = true; + vpd->flag = 1; + ret = pci_vpd_pci22_wait(dev); + if (ret < 0) + goto out; + ret = pci_user_read_config_dword(dev, vpd->cap + PCI_VPD_DATA, + &val); +out: + spin_unlock_irq(&vpd->lock); + if (ret < 0) + return ret; + + /* Convert to bytes */ + begin = pos & 3; + end = min(4, begin + size); + for (i = 0; i < end; ++i) { + if (i >= begin) + *buf++ = val; + val >>= 8; + } + return end - begin; +} + +static int pci_vpd_pci22_write(struct pci_dev *dev, int pos, int size, + const char *buf) +{ + struct pci_vpd_pci22 *vpd = + container_of(dev->vpd, struct pci_vpd_pci22, base); + u32 val; + int ret; + + if (pos < 0 || pos > PCI_VPD_PCI22_SIZE || pos & 3 || + size > PCI_VPD_PCI22_SIZE - pos || size < 4) + return -EINVAL; + + val = (u8) *buf++; + val |= ((u8) *buf++) << 8; + val |= ((u8) *buf++) << 16; + val |= ((u32)(u8) *buf++) << 24; + + spin_lock_irq(&vpd->lock); + ret = pci_vpd_pci22_wait(dev); + if (ret < 0) + goto out; + ret = pci_user_write_config_dword(dev, vpd->cap + PCI_VPD_DATA, + val); + if (ret < 0) + goto out; + ret = pci_user_write_config_word(dev, vpd->cap + PCI_VPD_ADDR, + pos | PCI_VPD_ADDR_F); + if (ret < 0) + goto out; + vpd->busy = true; + vpd->flag = 0; + ret = pci_vpd_pci22_wait(dev); +out: + spin_unlock_irq(&vpd->lock); + if (ret < 0) + return ret; + + return 4; +} + +static int pci_vpd_pci22_get_size(struct pci_dev *dev) +{ + return PCI_VPD_PCI22_SIZE; +} + +static void pci_vpd_pci22_release(struct pci_dev *dev) +{ + kfree(container_of(dev->vpd, struct pci_vpd_pci22, base)); +} + +static struct pci_vpd_ops pci_vpd_pci22_ops = { + .read = pci_vpd_pci22_read, + .write = pci_vpd_pci22_write, + .get_size = pci_vpd_pci22_get_size, + .release = pci_vpd_pci22_release, +}; + +int pci_vpd_pci22_init(struct pci_dev *dev) +{ + struct pci_vpd_pci22 *vpd; + u8 cap; + + cap = pci_find_capability(dev, PCI_CAP_ID_VPD); + if (!cap) + return -ENODEV; + vpd = kzalloc(sizeof(*vpd), GFP_ATOMIC); + if (!vpd) + return -ENOMEM; + + vpd->base.ops = &pci_vpd_pci22_ops; + spin_lock_init(&vpd->lock); + vpd->cap = cap; + vpd->busy = false; + dev->vpd = &vpd->base; + return 0; +} + /** * pci_block_user_cfg_access - Block userspace PCI config reads/writes * @dev: pci device struct diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c index f5b0b622c189..ae9a7695be97 100644 --- a/drivers/pci/pci-sysfs.c +++ b/drivers/pci/pci-sysfs.c @@ -343,6 +343,58 @@ pci_write_config(struct kobject *kobj, struct bin_attribute *bin_attr, return count; } +static ssize_t +pci_read_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct pci_dev *dev = + to_pci_dev(container_of(kobj, struct device, kobj)); + int end; + int ret; + + if (off > bin_attr->size) + count = 0; + else if (count > bin_attr->size - off) + count = bin_attr->size - off; + end = off + count; + + while (off < end) { + ret = dev->vpd->ops->read(dev, off, end - off, buf); + if (ret < 0) + return ret; + buf += ret; + off += ret; + } + + return count; +} + +static ssize_t +pci_write_vpd(struct kobject *kobj, struct bin_attribute *bin_attr, + char *buf, loff_t off, size_t count) +{ + struct pci_dev *dev = + to_pci_dev(container_of(kobj, struct device, kobj)); + int end; + int ret; + + if (off > bin_attr->size) + count = 0; + else if (count > bin_attr->size - off) + count = bin_attr->size - off; + end = off + count; + + while (off < end) { + ret = dev->vpd->ops->write(dev, off, end - off, buf); + if (ret < 0) + return ret; + buf += ret; + off += ret; + } + + return count; +} + #ifdef HAVE_PCI_LEGACY /** * pci_read_legacy_io - read byte(s) from legacy I/O port space @@ -611,7 +663,7 @@ int __attribute__ ((weak)) pcibios_add_platform_entries(struct pci_dev *dev) int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) { - struct bin_attribute *rom_attr = NULL; + struct bin_attribute *attr = NULL; int retval; if (!sysfs_initialized) @@ -624,22 +676,41 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) if (retval) goto err; + /* If the device has VPD, try to expose it in sysfs. */ + if (pdev->vpd) { + attr = kzalloc(sizeof(*attr), GFP_ATOMIC); + if (attr) { + pdev->vpd->attr = attr; + attr->size = pdev->vpd->ops->get_size(pdev); + attr->attr.name = "vpd"; + attr->attr.mode = S_IRUGO | S_IWUSR; + attr->read = pci_read_vpd; + attr->write = pci_write_vpd; + retval = sysfs_create_bin_file(&pdev->dev.kobj, attr); + if (retval) + goto err_vpd; + } else { + retval = -ENOMEM; + goto err_config_file; + } + } + retval = pci_create_resource_files(pdev); if (retval) - goto err_bin_file; + goto err_vpd_file; /* If the device has a ROM, try to expose it in sysfs. */ if (pci_resource_len(pdev, PCI_ROM_RESOURCE) || (pdev->resource[PCI_ROM_RESOURCE].flags & IORESOURCE_ROM_SHADOW)) { - rom_attr = kzalloc(sizeof(*rom_attr), GFP_ATOMIC); - if (rom_attr) { - pdev->rom_attr = rom_attr; - rom_attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); - rom_attr->attr.name = "rom"; - rom_attr->attr.mode = S_IRUSR; - rom_attr->read = pci_read_rom; - rom_attr->write = pci_write_rom; - retval = sysfs_create_bin_file(&pdev->dev.kobj, rom_attr); + attr = kzalloc(sizeof(*attr), GFP_ATOMIC); + if (attr) { + pdev->rom_attr = attr; + attr->size = pci_resource_len(pdev, PCI_ROM_RESOURCE); + attr->attr.name = "rom"; + attr->attr.mode = S_IRUSR; + attr->read = pci_read_rom; + attr->write = pci_write_rom; + retval = sysfs_create_bin_file(&pdev->dev.kobj, attr); if (retval) goto err_rom; } else { @@ -657,12 +728,18 @@ int __must_check pci_create_sysfs_dev_files (struct pci_dev *pdev) err_rom_file: if (pci_resource_len(pdev, PCI_ROM_RESOURCE)) - sysfs_remove_bin_file(&pdev->dev.kobj, rom_attr); + sysfs_remove_bin_file(&pdev->dev.kobj, pdev->rom_attr); err_rom: - kfree(rom_attr); + kfree(pdev->rom_attr); err_resource_files: pci_remove_resource_files(pdev); -err_bin_file: +err_vpd_file: + if (pdev->vpd) { + sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr); +err_vpd: + kfree(pdev->vpd->attr); + } +err_config_file: if (pdev->cfg_size < 4096) sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); else @@ -684,6 +761,10 @@ void pci_remove_sysfs_dev_files(struct pci_dev *pdev) pcie_aspm_remove_sysfs_dev_files(pdev); + if (pdev->vpd) { + sysfs_remove_bin_file(&pdev->dev.kobj, pdev->vpd->attr); + kfree(pdev->vpd->attr); + } if (pdev->cfg_size < 4096) sysfs_remove_bin_file(&pdev->dev.kobj, &pci_config_attr); else diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h index eabeb1f2ec99..0a497c1b4227 100644 --- a/drivers/pci/pci.h +++ b/drivers/pci/pci.h @@ -18,6 +18,25 @@ extern int pci_user_write_config_byte(struct pci_dev *dev, int where, u8 val); extern int pci_user_write_config_word(struct pci_dev *dev, int where, u16 val); extern int pci_user_write_config_dword(struct pci_dev *dev, int where, u32 val); +struct pci_vpd_ops { + int (*read)(struct pci_dev *dev, int pos, int size, char *buf); + int (*write)(struct pci_dev *dev, int pos, int size, const char *buf); + int (*get_size)(struct pci_dev *dev); + void (*release)(struct pci_dev *dev); +}; + +struct pci_vpd { + struct pci_vpd_ops *ops; + struct bin_attribute *attr; /* descriptor for sysfs VPD entry */ +}; + +extern int pci_vpd_pci22_init(struct pci_dev *dev); +static inline void pci_vpd_release(struct pci_dev *dev) +{ + if (dev->vpd) + dev->vpd->ops->release(dev); +} + /* PCI /proc functions */ #ifdef CONFIG_PROC_FS extern int pci_proc_attach_device(struct pci_dev *dev); diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index 284ef392c3ea..c2e99fd87faf 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c @@ -794,6 +794,7 @@ static void pci_release_dev(struct device *dev) struct pci_dev *pci_dev; pci_dev = to_pci_dev(dev); + pci_vpd_release(pci_dev); kfree(pci_dev); } @@ -933,6 +934,8 @@ pci_scan_device(struct pci_bus *bus, int devfn) return NULL; } + pci_vpd_pci22_init(dev); + return dev; } diff --git a/include/linux/pci.h b/include/linux/pci.h index e2f46b05cf8b..292491324b01 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -20,6 +20,8 @@ /* Include the pci register defines */ #include +struct pci_vpd; + /* * The PCI interface treats multi-function devices as independent * devices. The slot/function address of each device is encoded @@ -206,6 +208,7 @@ struct pci_dev { #ifdef CONFIG_PCI_MSI struct list_head msi_list; #endif + struct pci_vpd *vpd; }; extern struct pci_dev *alloc_pci_dev(void); -- cgit v1.2.3 From 0a0c4114df4a6903bccb65b06cabb6ddc968f877 Mon Sep 17 00:00:00 2001 From: Akinobu Mita Date: Wed, 26 Mar 2008 12:09:02 +0100 Subject: cdrom: make unregister_cdrom() return void Now unregister_cdrom() always returns 0. Make it return void and update all callers that check the return value. Signed-off-by: Akinobu Mita Cc: Adrian McMenamin Cc: Borislav Petkov Signed-off-by: Jens Axboe --- Documentation/cdrom/cdrom-standard.tex | 2 +- drivers/cdrom/cdrom.c | 3 +-- drivers/cdrom/gdrom.c | 4 +++- drivers/cdrom/viocd.c | 5 +---- drivers/ide/ide-cd.c | 5 ++--- include/linux/cdrom.h | 2 +- 6 files changed, 9 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/cdrom/cdrom-standard.tex b/Documentation/cdrom/cdrom-standard.tex index c713aeb020c4..c06233fe52ac 100644 --- a/Documentation/cdrom/cdrom-standard.tex +++ b/Documentation/cdrom/cdrom-standard.tex @@ -777,7 +777,7 @@ Note that a driver must have one static structure, $_dops$, while it may have as many structures $_info$ as there are minor devices active. $Register_cdrom()$ builds a linked list from these. -\subsection{$Int\ unregister_cdrom(struct\ cdrom_device_info * cdi)$} +\subsection{$Void\ unregister_cdrom(struct\ cdrom_device_info * cdi)$} Unregistering device $cdi$ with minor number $MINOR(cdi\to dev)$ removes the minor device from the list. If it was the last registered minor for diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index c4213b7d0b20..663a7f7dc580 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c @@ -442,7 +442,7 @@ int register_cdrom(struct cdrom_device_info *cdi) } #undef ENSURE -int unregister_cdrom(struct cdrom_device_info *cdi) +void unregister_cdrom(struct cdrom_device_info *cdi) { cdinfo(CD_OPEN, "entering unregister_cdrom\n"); @@ -455,7 +455,6 @@ int unregister_cdrom(struct cdrom_device_info *cdi) cdi->ops->n_minors--; cdinfo(CD_REG_UNREG, "drive \"/dev/%s\" unregistered\n", cdi->name); - return 0; } int cdrom_get_media_event(struct cdrom_device_info *cdi, diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 4e2bbcccc064..71ec426ecffc 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c @@ -827,7 +827,9 @@ static int __devexit remove_gdrom(struct platform_device *devptr) del_gendisk(gd.disk); if (gdrom_major) unregister_blkdev(gdrom_major, GDROM_DEV_NAME); - return unregister_cdrom(gd.cd_info); + unregister_cdrom(gd.cd_info); + + return 0; } static struct platform_driver gdrom_driver = { diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index cac06bc1754b..b74b6c2768a8 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c @@ -650,10 +650,7 @@ static int viocd_remove(struct vio_dev *vdev) { struct disk_info *d = &viocd_diskinfo[vdev->unit_address]; - if (unregister_cdrom(&d->viocd_info) != 0) - printk(VIOCD_KERN_WARNING - "Cannot unregister viocd CD-ROM %s!\n", - d->viocd_info.name); + unregister_cdrom(&d->viocd_info); del_gendisk(d->viocd_disk); blk_cleanup_queue(d->viocd_disk->queue); put_disk(d->viocd_disk); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 396000208f81..fe5aefbf8339 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -2032,9 +2032,8 @@ static void ide_cd_release(struct kref *kref) kfree(info->buffer); kfree(info->toc); - if (devinfo->handle == drive && unregister_cdrom(devinfo)) - printk(KERN_ERR "%s: %s failed to unregister device from the cdrom " - "driver.\n", __FUNCTION__, drive->name); + if (devinfo->handle == drive) + unregister_cdrom(devinfo); drive->dsc_overlap = 0; drive->driver_data = NULL; blk_queue_prep_rq(drive->queue, NULL); diff --git a/include/linux/cdrom.h b/include/linux/cdrom.h index 40e05d0a6e45..5db265ea60f6 100644 --- a/include/linux/cdrom.h +++ b/include/linux/cdrom.h @@ -995,7 +995,7 @@ extern int cdrom_ioctl(struct file *file, struct cdrom_device_info *cdi, extern int cdrom_media_changed(struct cdrom_device_info *); extern int register_cdrom(struct cdrom_device_info *cdi); -extern int unregister_cdrom(struct cdrom_device_info *cdi); +extern void unregister_cdrom(struct cdrom_device_info *cdi); typedef struct { int data; -- cgit v1.2.3 From ec98c6b9b47df6df1c1fa6cf3d427414f8c2cf16 Mon Sep 17 00:00:00 2001 From: "David S. Miller" Date: Sun, 20 Apr 2008 02:14:23 -0700 Subject: [SPARC]: Remove SunOS and Solaris binary support. As per Documentation/feature-removal-schedule.txt Signed-off-by: David S. Miller --- Documentation/feature-removal-schedule.txt | 11 - Documentation/highuid.txt | 2 - Documentation/magic-number.txt | 1 - arch/sparc/Kconfig | 12 - arch/sparc/defconfig | 165 ++-- arch/sparc/kernel/Makefile | 10 +- arch/sparc/kernel/entry.S | 206 +---- arch/sparc/kernel/errtbls.c | 144 --- arch/sparc/kernel/head.S | 37 +- arch/sparc/kernel/sclow.S | 86 -- arch/sparc/kernel/signal.c | 307 +------ arch/sparc/kernel/sparc_ksyms.c | 8 - arch/sparc/kernel/sunos_asm.S | 67 -- arch/sparc/kernel/sunos_ioctl.c | 230 ----- arch/sparc/kernel/sys_solaris.c | 35 - arch/sparc/kernel/sys_sunos.c | 1210 ------------------------- arch/sparc/kernel/systbls.S | 121 --- arch/sparc64/Kconfig | 47 +- arch/sparc64/Makefile | 1 - arch/sparc64/defconfig | 29 +- arch/sparc64/kernel/Makefile | 9 - arch/sparc64/kernel/binfmt_aout32.c | 419 --------- arch/sparc64/kernel/entry.S | 61 +- arch/sparc64/kernel/signal.c | 1 - arch/sparc64/kernel/signal32.c | 300 +----- arch/sparc64/kernel/sparc64_ksyms.c | 41 - arch/sparc64/kernel/sunos_ioctl32.c | 275 ------ arch/sparc64/kernel/sys_sparc.c | 38 - arch/sparc64/kernel/sys_sunos32.c | 1359 ---------------------------- arch/sparc64/kernel/systbls.S | 122 --- arch/sparc64/kernel/systbls.h | 2 - arch/sparc64/kernel/ttable.S | 14 +- arch/sparc64/solaris/Makefile | 10 - arch/sparc64/solaris/conv.h | 38 - arch/sparc64/solaris/entry64.S | 223 ----- arch/sparc64/solaris/fs.c | 745 --------------- arch/sparc64/solaris/ioctl.c | 825 ----------------- arch/sparc64/solaris/ipc.c | 126 --- arch/sparc64/solaris/misc.c | 786 ---------------- arch/sparc64/solaris/signal.c | 429 --------- arch/sparc64/solaris/signal.h | 108 --- arch/sparc64/solaris/socket.c | 461 ---------- arch/sparc64/solaris/socksys.c | 203 ----- arch/sparc64/solaris/socksys.h | 208 ----- arch/sparc64/solaris/systbl.S | 285 ------ arch/sparc64/solaris/timod.c | 976 -------------------- fs/Kconfig.binfmt | 2 +- include/asm-sparc/Kbuild | 1 - include/asm-sparc/a.out-core.h | 52 -- include/asm-sparc/a.out.h | 97 -- include/asm-sparc/head.h | 33 - include/asm-sparc/ioctls.h | 2 - include/asm-sparc/mman.h | 13 - include/asm-sparc/namei.h | 15 +- include/asm-sparc/pconf.h | 25 - include/asm-sparc/processor.h | 3 - include/asm-sparc/socket.h | 3 - include/asm-sparc/solerrno.h | 132 --- include/asm-sparc/svr4.h | 119 --- include/asm-sparc/termios.h | 5 - include/asm-sparc/user.h | 56 +- include/asm-sparc64/Kbuild | 1 - include/asm-sparc64/a.out-core.h | 31 - include/asm-sparc64/a.out.h | 1 - include/asm-sparc64/ioctls.h | 2 - include/asm-sparc64/mman.h | 13 - include/asm-sparc64/namei.h | 15 +- include/asm-sparc64/pconf.h | 25 - include/asm-sparc64/socket.h | 3 - include/asm-sparc64/solerrno.h | 132 --- include/asm-sparc64/svr4.h | 120 --- include/asm-sparc64/termios.h | 5 - include/asm-sparc64/ttable.h | 18 - include/asm-sparc64/unistd.h | 10 - include/asm-sparc64/user.h | 61 +- net/core/sock.c | 9 - 76 files changed, 172 insertions(+), 11625 deletions(-) delete mode 100644 arch/sparc/kernel/errtbls.c delete mode 100644 arch/sparc/kernel/sclow.S delete mode 100644 arch/sparc/kernel/sunos_asm.S delete mode 100644 arch/sparc/kernel/sunos_ioctl.c delete mode 100644 arch/sparc/kernel/sys_solaris.c delete mode 100644 arch/sparc/kernel/sys_sunos.c delete mode 100644 arch/sparc64/kernel/binfmt_aout32.c delete mode 100644 arch/sparc64/kernel/sunos_ioctl32.c delete mode 100644 arch/sparc64/kernel/sys_sunos32.c delete mode 100644 arch/sparc64/solaris/Makefile delete mode 100644 arch/sparc64/solaris/conv.h delete mode 100644 arch/sparc64/solaris/entry64.S delete mode 100644 arch/sparc64/solaris/fs.c delete mode 100644 arch/sparc64/solaris/ioctl.c delete mode 100644 arch/sparc64/solaris/ipc.c delete mode 100644 arch/sparc64/solaris/misc.c delete mode 100644 arch/sparc64/solaris/signal.c delete mode 100644 arch/sparc64/solaris/signal.h delete mode 100644 arch/sparc64/solaris/socket.c delete mode 100644 arch/sparc64/solaris/socksys.c delete mode 100644 arch/sparc64/solaris/socksys.h delete mode 100644 arch/sparc64/solaris/systbl.S delete mode 100644 arch/sparc64/solaris/timod.c delete mode 100644 include/asm-sparc/a.out-core.h delete mode 100644 include/asm-sparc/a.out.h delete mode 100644 include/asm-sparc/pconf.h delete mode 100644 include/asm-sparc/solerrno.h delete mode 100644 include/asm-sparc/svr4.h delete mode 100644 include/asm-sparc64/a.out-core.h delete mode 100644 include/asm-sparc64/a.out.h delete mode 100644 include/asm-sparc64/pconf.h delete mode 100644 include/asm-sparc64/solerrno.h delete mode 100644 include/asm-sparc64/svr4.h (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index af0e9393bf68..76ab78e83bb1 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -261,17 +261,6 @@ Who: Michael Buesch --------------------------- -What: Solaris/SunOS syscall and binary support on Sparc -When: 2.6.26 -Why: Largely unmaintained and almost entirely unused. File system - layering used to divert library and dynamic linker searches to - /usr/gnemul is extremely buggy and unfixable. Making it work - is largely pointless as without a lot of work only the most - trivial of Solaris binaries can work with the emulation code. -Who: David S. Miller - ---------------------------- - What: init_mm export When: 2.6.26 Why: Not used in-tree. The current out-of-tree users used it to diff --git a/Documentation/highuid.txt b/Documentation/highuid.txt index 76034d9dbfc0..6bad6f1d1cac 100644 --- a/Documentation/highuid.txt +++ b/Documentation/highuid.txt @@ -28,8 +28,6 @@ What's left to be done for 32-bit UIDs on all Linux architectures: uses the 32-bit UID system calls properly otherwise. This affects at least: - SunOS emulation - Solaris emulation iBCS on Intel sparc32 emulation on sparc64 diff --git a/Documentation/magic-number.txt b/Documentation/magic-number.txt index bd450e797558..95070028d15e 100644 --- a/Documentation/magic-number.txt +++ b/Documentation/magic-number.txt @@ -95,7 +95,6 @@ RFCOMM_TTY_MAGIC 0x6d02 net/bluetooth/rfcomm/tty.c USB_SERIAL_PORT_MAGIC 0x7301 usb_serial_port drivers/usb/serial/usb-serial.h CG_MAGIC 0x00090255 ufs_cylinder_group include/linux/ufs_fs.h A2232_MAGIC 0x000a2232 gs_port drivers/char/ser_a2232.h -SOLARIS_SOCKET_MAGIC 0x000ADDED sol_socket_struct arch/sparc64/solaris/socksys.h RPORT_MAGIC 0x00525001 r_port drivers/char/rocket_int.h LSEMAGIC 0x05091998 lse drivers/fc4/fc.c GDTIOCTL_MAGIC 0x06030f07 gdth_iowr_str drivers/scsi/gdth_ioctl.h diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index c40343c54920..49590f8fe98c 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -27,9 +27,6 @@ config ARCH_NO_VIRT_TO_BUS config OF def_bool y -config ARCH_SUPPORTS_AOUT - def_bool y - config HZ int default 100 @@ -257,15 +254,6 @@ config SPARC_LED source "fs/Kconfig.binfmt" -config SUNOS_EMUL - bool "SunOS binary emulation" - help - This allows you to run most SunOS binaries. If you want to do this, - say Y here and place appropriate files in /usr/gnemul/sunos. See - for more information. If you - want to run SunOS binaries on an Ultra you must also say Y to - "Kernel support for 32-bit a.out binaries" above. - source "mm/Kconfig" endmenu diff --git a/arch/sparc/defconfig b/arch/sparc/defconfig index f7a509149199..6a2c57a2fe71 100644 --- a/arch/sparc/defconfig +++ b/arch/sparc/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.23-rc1 -# Wed Jul 25 15:30:21 2007 +# Linux kernel version: 2.6.25 +# Sun Apr 20 01:49:51 2008 # CONFIG_MMU=y CONFIG_HIGHMEM=y @@ -9,18 +9,15 @@ CONFIG_ZONE_DMA=y CONFIG_GENERIC_ISA_DMA=y CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_OF=y +CONFIG_HZ=100 CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" # -# Code maturity level options +# General setup # CONFIG_EXPERIMENTAL=y CONFIG_BROKEN_ON_SMP=y CONFIG_INIT_ENV_ARG_LIMIT=32 - -# -# General setup -# CONFIG_LOCALVERSION="" CONFIG_LOCALVERSION_AUTO=y CONFIG_SWAP=y @@ -29,12 +26,23 @@ CONFIG_SYSVIPC_SYSCTL=y CONFIG_POSIX_MQUEUE=y # CONFIG_BSD_PROCESS_ACCT is not set # CONFIG_TASKSTATS is not set -# CONFIG_USER_NS is not set # CONFIG_AUDIT is not set # CONFIG_IKCONFIG is not set CONFIG_LOG_BUF_SHIFT=14 +# CONFIG_CGROUPS is not set +CONFIG_GROUP_SCHED=y +CONFIG_FAIR_GROUP_SCHED=y +CONFIG_RT_GROUP_SCHED=y +CONFIG_USER_SCHED=y +# CONFIG_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y # CONFIG_RELAY is not set +CONFIG_NAMESPACES=y +# CONFIG_UTS_NS is not set +# CONFIG_IPC_NS is not set +# CONFIG_USER_NS is not set +# CONFIG_PID_NS is not set CONFIG_BLK_DEV_INITRD=y CONFIG_INITRAMFS_SOURCE="" # CONFIG_CC_OPTIMIZE_FOR_SIZE is not set @@ -49,6 +57,7 @@ CONFIG_HOTPLUG=y CONFIG_PRINTK=y CONFIG_BUG=y CONFIG_ELF_CORE=y +CONFIG_COMPAT_BRK=y CONFIG_BASE_FULL=y CONFIG_FUTEX=y CONFIG_ANON_INODES=y @@ -61,6 +70,13 @@ CONFIG_VM_EVENT_COUNTERS=y CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set +# CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set +CONFIG_HAVE_OPROFILE=y +# CONFIG_HAVE_KPROBES is not set +# CONFIG_HAVE_KRETPROBES is not set +CONFIG_PROC_PAGE_MONITOR=y +CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y # CONFIG_TINY_SHMEM is not set CONFIG_BASE_SMALL=0 @@ -88,6 +104,7 @@ CONFIG_IOSCHED_CFQ=y CONFIG_DEFAULT_CFQ=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="cfq" +CONFIG_CLASSIC_RCU=y # # General machine setup @@ -113,14 +130,13 @@ CONFIG_SUN_PM=y CONFIG_PCI=y CONFIG_PCI_SYSCALL=y # CONFIG_ARCH_SUPPORTS_MSI is not set +CONFIG_PCI_LEGACY=y # CONFIG_PCI_DEBUG is not set # CONFIG_NO_DMA is not set CONFIG_SUN_OPENPROMFS=m # CONFIG_SPARC_LED is not set CONFIG_BINFMT_ELF=y -CONFIG_BINFMT_AOUT=y CONFIG_BINFMT_MISC=m -CONFIG_SUNOS_EMUL=y CONFIG_SELECT_MEMORY_MODEL=y CONFIG_FLATMEM_MANUAL=y # CONFIG_DISCONTIGMEM_MANUAL is not set @@ -128,6 +144,7 @@ CONFIG_FLATMEM_MANUAL=y CONFIG_FLATMEM=y CONFIG_FLAT_NODE_MEM_MAP=y # CONFIG_SPARSEMEM_STATIC is not set +# CONFIG_SPARSEMEM_VMEMMAP_ENABLE is not set CONFIG_SPLIT_PTLOCK_CPUS=4 # CONFIG_RESOURCES_64BIT is not set CONFIG_ZONE_DMA_FLAG=1 @@ -148,6 +165,7 @@ CONFIG_XFRM=y CONFIG_XFRM_USER=m # CONFIG_XFRM_SUB_POLICY is not set # CONFIG_XFRM_MIGRATE is not set +# CONFIG_XFRM_STATISTICS is not set CONFIG_NET_KEY=m # CONFIG_NET_KEY_MIGRATE is not set CONFIG_INET=y @@ -170,6 +188,7 @@ CONFIG_INET_TUNNEL=y CONFIG_INET_XFRM_MODE_TRANSPORT=y CONFIG_INET_XFRM_MODE_TUNNEL=y CONFIG_INET_XFRM_MODE_BEET=y +# CONFIG_INET_LRO is not set CONFIG_INET_DIAG=y CONFIG_INET_TCP_DIAG=y # CONFIG_TCP_CONG_ADVANCED is not set @@ -191,8 +210,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_INET6_XFRM_MODE_BEET=m # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m # CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set # CONFIG_IP_DCCP is not set @@ -214,10 +235,6 @@ CONFIG_SCTP_HMAC_MD5=y # CONFIG_LAPB is not set # CONFIG_ECONET is not set # CONFIG_WAN_ROUTER is not set - -# -# QoS and/or fair queueing -# # CONFIG_NET_SCHED is not set # @@ -225,6 +242,7 @@ CONFIG_SCTP_HMAC_MD5=y # CONFIG_NET_PKTGEN=m # CONFIG_HAMRADIO is not set +# CONFIG_CAN is not set # CONFIG_IRDA is not set # CONFIG_BT is not set CONFIG_AF_RXRPC=m @@ -248,6 +266,7 @@ CONFIG_AF_RXRPC=m # # Generic Driver Options # +CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y # CONFIG_FW_LOADER is not set @@ -271,7 +290,7 @@ CONFIG_BLK_DEV_CRYPTOLOOP=m CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 -CONFIG_BLK_DEV_RAM_BLOCKSIZE=1024 +# CONFIG_BLK_DEV_XIP is not set # CONFIG_CDROM_PKTCDVD is not set # CONFIG_ATA_OVER_ETH is not set CONFIG_MISC_DEVICES=y @@ -279,6 +298,8 @@ CONFIG_MISC_DEVICES=y # CONFIG_EEPROM_93CX6 is not set # CONFIG_SGI_IOC4 is not set # CONFIG_TIFM_CORE is not set +# CONFIG_ENCLOSURE_SERVICES is not set +CONFIG_HAVE_IDE=y # CONFIG_IDE is not set # @@ -318,6 +339,7 @@ CONFIG_SCSI_SPI_ATTRS=y # CONFIG_SCSI_FC_ATTRS is not set # CONFIG_SCSI_ISCSI_ATTRS is not set # CONFIG_SCSI_SAS_LIBSAS is not set +# CONFIG_SCSI_SRP_ATTRS is not set CONFIG_SCSI_LOWLEVEL=y # CONFIG_ISCSI_TCP is not set # CONFIG_BLK_DEV_3W_XXXX_RAID is not set @@ -338,6 +360,7 @@ CONFIG_SCSI_LOWLEVEL=y # CONFIG_SCSI_IPS is not set # CONFIG_SCSI_INITIO is not set # CONFIG_SCSI_INIA100 is not set +# CONFIG_SCSI_MVSAS is not set # CONFIG_SCSI_STEX is not set # CONFIG_SCSI_SYM53C8XX_2 is not set # CONFIG_SCSI_QLOGIC_1280 is not set @@ -353,14 +376,7 @@ CONFIG_SCSI_SUNESP=y # CONFIG_SCSI_SRP is not set # CONFIG_ATA is not set # CONFIG_MD is not set - -# -# Fusion MPT device support -# # CONFIG_FUSION is not set -# CONFIG_FUSION_SPI is not set -# CONFIG_FUSION_FC is not set -# CONFIG_FUSION_SAS is not set # # IEEE 1394 (FireWire) support @@ -375,6 +391,7 @@ CONFIG_DUMMY=m # CONFIG_MACVLAN is not set # CONFIG_EQUALIZER is not set CONFIG_TUN=m +# CONFIG_VETH is not set # CONFIG_ARCNET is not set # CONFIG_PHYLIB is not set CONFIG_NET_ETHERNET=y @@ -388,11 +405,20 @@ CONFIG_SUNQE=m # CONFIG_NET_VENDOR_3COM is not set # CONFIG_NET_TULIP is not set # CONFIG_HP100 is not set +# CONFIG_IBM_NEW_EMAC_ZMII is not set +# CONFIG_IBM_NEW_EMAC_RGMII is not set +# CONFIG_IBM_NEW_EMAC_TAH is not set +# CONFIG_IBM_NEW_EMAC_EMAC4 is not set # CONFIG_NET_PCI is not set +# CONFIG_B44 is not set CONFIG_NETDEV_1000=y # CONFIG_ACENIC is not set # CONFIG_DL2K is not set # CONFIG_E1000 is not set +# CONFIG_E1000E is not set +# CONFIG_E1000E_ENABLED is not set +# CONFIG_IP1000 is not set +# CONFIG_IGB is not set # CONFIG_MYRI_SBUS is not set # CONFIG_NS83820 is not set # CONFIG_HAMACHI is not set @@ -409,11 +435,15 @@ CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y # CONFIG_CHELSIO_T1 is not set # CONFIG_CHELSIO_T3 is not set +# CONFIG_IXGBE is not set # CONFIG_IXGB is not set # CONFIG_S2IO is not set # CONFIG_MYRI10GE is not set # CONFIG_NETXEN_NIC is not set +# CONFIG_NIU is not set # CONFIG_MLX4_CORE is not set +# CONFIG_TEHUTI is not set +# CONFIG_BNX2X is not set # CONFIG_TR is not set # @@ -421,13 +451,13 @@ CONFIG_NETDEV_10000=y # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set # CONFIG_WAN is not set # CONFIG_FDDI is not set # CONFIG_HIPPI is not set # CONFIG_PPP is not set # CONFIG_SLIP is not set # CONFIG_NET_FC is not set -# CONFIG_SHAPER is not set # CONFIG_NETCONSOLE is not set # CONFIG_NETPOLL is not set # CONFIG_NET_POLL_CONTROLLER is not set @@ -449,7 +479,6 @@ CONFIG_INPUT_MOUSEDEV_PSAUX=y CONFIG_INPUT_MOUSEDEV_SCREEN_X=1024 CONFIG_INPUT_MOUSEDEV_SCREEN_Y=768 CONFIG_INPUT_JOYDEV=m -# CONFIG_INPUT_TSDEV is not set CONFIG_INPUT_EVDEV=m CONFIG_INPUT_EVBUG=m @@ -498,6 +527,7 @@ CONFIG_VT_CONSOLE=y CONFIG_HW_CONSOLE=y # CONFIG_VT_HW_CONSOLE_BINDING is not set # CONFIG_SERIAL_NONSTANDARD is not set +# CONFIG_NOZOMI is not set # # Serial drivers @@ -519,7 +549,6 @@ CONFIG_UNIX98_PTYS=y CONFIG_LEGACY_PTYS=y CONFIG_LEGACY_PTY_COUNT=256 # CONFIG_IPMI_HANDLER is not set -# CONFIG_WATCHDOG is not set CONFIG_HW_RANDOM=m CONFIG_JS_RTC=m # CONFIG_R3964 is not set @@ -538,9 +567,9 @@ CONFIG_DEVPORT=y # CONFIG_POWER_SUPPLY is not set CONFIG_HWMON=y # CONFIG_HWMON_VID is not set -# CONFIG_SENSORS_ABITUGURU is not set -# CONFIG_SENSORS_ABITUGURU3 is not set +# CONFIG_SENSORS_I5K_AMB is not set # CONFIG_SENSORS_F71805F is not set +# CONFIG_SENSORS_F71882FG is not set # CONFIG_SENSORS_IT87 is not set # CONFIG_SENSORS_PC87360 is not set # CONFIG_SENSORS_PC87427 is not set @@ -553,6 +582,14 @@ CONFIG_HWMON=y # CONFIG_SENSORS_W83627HF is not set # CONFIG_SENSORS_W83627EHF is not set # CONFIG_HWMON_DEBUG_CHIP is not set +# CONFIG_THERMAL is not set +# CONFIG_WATCHDOG is not set + +# +# Sonics Silicon Backplane +# +CONFIG_SSB_POSSIBLE=y +# CONFIG_SSB is not set # # Multifunction device drivers @@ -569,15 +606,15 @@ CONFIG_HWMON=y # # Graphics support # +# CONFIG_VGASTATE is not set +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Display device support # # CONFIG_DISPLAY_SUPPORT is not set -# CONFIG_VGASTATE is not set -# CONFIG_VIDEO_OUTPUT_CONTROL is not set -# CONFIG_FB is not set # # Console display driver support @@ -592,6 +629,7 @@ CONFIG_DUMMY_CONSOLE=y CONFIG_HID_SUPPORT=y CONFIG_HID=y # CONFIG_HID_DEBUG is not set +# CONFIG_HIDRAW is not set CONFIG_USB_SUPPORT=y CONFIG_USB_ARCH_HAS_HCD=y CONFIG_USB_ARCH_HAS_OHCI=y @@ -601,33 +639,13 @@ CONFIG_USB_ARCH_HAS_EHCI=y # # NOTE: USB_STORAGE enables SCSI, and 'SCSI disk support' # - -# -# USB Gadget Support -# # CONFIG_USB_GADGET is not set # CONFIG_MMC is not set +# CONFIG_MEMSTICK is not set # CONFIG_NEW_LEDS is not set # CONFIG_INFINIBAND is not set - -# -# Real Time Clock -# # CONFIG_RTC_CLASS is not set -# -# DMA Engine support -# -# CONFIG_DMA_ENGINE is not set - -# -# DMA Clients -# - -# -# DMA Devices -# - # # Userspace I/O # @@ -664,18 +682,14 @@ CONFIG_FS_MBCACHE=y CONFIG_FS_POSIX_ACL=y CONFIG_XFS_FS=m CONFIG_XFS_QUOTA=y -CONFIG_XFS_SECURITY=y CONFIG_XFS_POSIX_ACL=y CONFIG_XFS_RT=y -# CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set -# CONFIG_MINIX_FS is not set -CONFIG_ROMFS_FS=m +CONFIG_DNOTIFY=y CONFIG_INOTIFY=y CONFIG_INOTIFY_USER=y # CONFIG_QUOTA is not set CONFIG_QUOTACTL=y -CONFIG_DNOTIFY=y CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m # CONFIG_FUSE_FS is not set @@ -704,7 +718,6 @@ CONFIG_PROC_SYSCTL=y CONFIG_SYSFS=y # CONFIG_TMPFS is not set # CONFIG_HUGETLB_PAGE is not set -CONFIG_RAMFS=y # CONFIG_CONFIGFS_FS is not set # @@ -721,14 +734,13 @@ CONFIG_BEFS_FS=m # CONFIG_EFS_FS is not set # CONFIG_CRAMFS is not set # CONFIG_VXFS_FS is not set +# CONFIG_MINIX_FS is not set # CONFIG_HPFS_FS is not set # CONFIG_QNX4FS_FS is not set +CONFIG_ROMFS_FS=m # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set - -# -# Network File Systems -# +CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y # CONFIG_NFS_V3 is not set # CONFIG_NFS_V4 is not set @@ -760,10 +772,6 @@ CONFIG_AFS_FS=m # CONFIG_PARTITION_ADVANCED is not set CONFIG_MSDOS_PARTITION=y CONFIG_SUN_PARTITION=y - -# -# Native Language Support -# CONFIG_NLS=y CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_CODEPAGE_437 is not set @@ -804,21 +812,14 @@ CONFIG_NLS_DEFAULT="iso8859-1" # CONFIG_NLS_KOI8_R is not set # CONFIG_NLS_KOI8_U is not set # CONFIG_NLS_UTF8 is not set - -# -# Distributed Lock Manager -# # CONFIG_DLM is not set -# -# Instrumentation Support -# -# CONFIG_PROFILING is not set - # # Kernel hacking # +CONFIG_TRACE_IRQFLAGS_SUPPORT=y # CONFIG_PRINTK_TIME is not set +# CONFIG_ENABLE_WARN_DEPRECATED is not set CONFIG_ENABLE_MUST_CHECK=y CONFIG_MAGIC_SYSRQ=y # CONFIG_UNUSED_SYMBOLS is not set @@ -842,9 +843,12 @@ CONFIG_DEBUG_BUGVERBOSE=y # CONFIG_DEBUG_INFO is not set # CONFIG_DEBUG_VM is not set # CONFIG_DEBUG_LIST is not set -CONFIG_FORCED_INLINING=y +# CONFIG_DEBUG_SG is not set +# CONFIG_BOOT_PRINTK_DELAY is not set # CONFIG_RCU_TORTURE_TEST is not set +# CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_FAULT_INJECTION is not set +# CONFIG_SAMPLES is not set # CONFIG_DEBUG_STACK_USAGE is not set # @@ -853,9 +857,12 @@ CONFIG_FORCED_INLINING=y CONFIG_KEYS=y # CONFIG_KEYS_DEBUG_PROC_KEYS is not set # CONFIG_SECURITY is not set +# CONFIG_SECURITY_FILE_CAPABILITIES is not set CONFIG_CRYPTO=y CONFIG_CRYPTO_ALGAPI=y +CONFIG_CRYPTO_AEAD=y CONFIG_CRYPTO_BLKCIPHER=y +# CONFIG_CRYPTO_SEQIV is not set CONFIG_CRYPTO_HASH=y CONFIG_CRYPTO_MANAGER=y CONFIG_CRYPTO_HMAC=y @@ -873,6 +880,10 @@ CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_LRW is not set +# CONFIG_CRYPTO_XTS is not set +# CONFIG_CRYPTO_CTR is not set +# CONFIG_CRYPTO_GCM is not set +# CONFIG_CRYPTO_CCM is not set # CONFIG_CRYPTO_CRYPTD is not set CONFIG_CRYPTO_DES=y # CONFIG_CRYPTO_FCRYPT is not set @@ -887,11 +898,15 @@ CONFIG_CRYPTO_CAST6=m CONFIG_CRYPTO_ARC4=m # CONFIG_CRYPTO_KHAZAD is not set # CONFIG_CRYPTO_ANUBIS is not set +# CONFIG_CRYPTO_SEED is not set +# CONFIG_CRYPTO_SALSA20 is not set CONFIG_CRYPTO_DEFLATE=y CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m # CONFIG_CRYPTO_CAMELLIA is not set # CONFIG_CRYPTO_TEST is not set +CONFIG_CRYPTO_AUTHENC=y +# CONFIG_CRYPTO_LZO is not set # CONFIG_CRYPTO_HW is not set # diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 2712bb166f6f..59700aaaae93 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile @@ -9,9 +9,9 @@ EXTRA_AFLAGS := -ansi IRQ_OBJS := irq.o sun4m_irq.o sun4c_irq.o sun4d_irq.o obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ process.o signal.o ioport.o setup.o idprom.o \ - sys_sparc.o sunos_asm.o systbls.o \ - time.o windows.o cpu.o devices.o sclow.o \ - tadpole.o tick14.o ptrace.o sys_solaris.o \ + sys_sparc.o systbls.o \ + time.o windows.o cpu.o devices.o \ + tadpole.o tick14.o ptrace.o \ unaligned.o una_asm.o muldiv.o \ prom.o of_device.o devres.o @@ -25,7 +25,3 @@ obj-$(CONFIG_PCI) += ebus.o obj-$(CONFIG_SUN_PM) += apc.o pmc.o obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o obj-$(CONFIG_SPARC_LED) += led.o - -ifdef CONFIG_SUNOS_EMUL -obj-y += sys_sunos.o sunos_ioctl.o -endif diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index c2eed8f71516..135644f8add7 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S @@ -1186,36 +1186,6 @@ srmmu_fault: RESTORE_ALL -#ifdef CONFIG_SUNOS_EMUL - /* SunOS uses syscall zero as the 'indirect syscall' it looks - * like indir_syscall(scall_num, arg0, arg1, arg2...); etc. - * This is complete brain damage. - */ - .globl sunos_indir -sunos_indir: - mov %o7, %l4 - cmp %o0, NR_SYSCALLS - blu,a 1f - sll %o0, 0x2, %o0 - - sethi %hi(sunos_nosys), %l6 - b 2f - or %l6, %lo(sunos_nosys), %l6 - -1: - set sunos_sys_table, %l7 - ld [%l7 + %o0], %l6 - -2: - mov %o1, %o0 - mov %o2, %o1 - mov %o3, %o2 - mov %o4, %o3 - mov %o5, %o4 - call %l6 - mov %l4, %o7 -#endif - .align 4 .globl sys_nis_syscall sys_nis_syscall: @@ -1232,6 +1202,16 @@ sys_execve: call sparc_execve mov %l5, %o7 + .globl sunos_execv +sunos_execv: + st %g0, [%sp + STACKFRAME_SZ + PT_I2] + + call sparc_execve + add %sp, STACKFRAME_SZ, %o0 + + b ret_sys_call + ld [%sp + STACKFRAME_SZ + PT_I0], %o0 + .align 4 .globl sys_pipe sys_pipe: @@ -1394,7 +1374,7 @@ ret_from_fork: b ret_sys_call ld [%sp + STACKFRAME_SZ + PT_I0], %o0 - /* Linux native and SunOS system calls enter here... */ + /* Linux native system calls enter here... */ .align 4 .globl linux_sparc_syscall linux_sparc_syscall: @@ -1472,170 +1452,6 @@ linux_syscall_trace2: st %l2, [%sp + STACKFRAME_SZ + PT_NPC] - /* - * Solaris system calls and indirect system calls enter here. - * - * I have named the solaris indirect syscalls like that because - * it seems like Solaris has some fast path syscalls that can - * be handled as indirect system calls. - mig - */ - -linux_syscall_for_solaris: - sethi %hi(sys_call_table), %l7 - b linux_sparc_syscall - or %l7, %lo(sys_call_table), %l7 - - .align 4 - .globl solaris_syscall -solaris_syscall: - cmp %g1,59 - be linux_syscall_for_solaris - cmp %g1,2 - be linux_syscall_for_solaris - cmp %g1,42 - be linux_syscall_for_solaris - cmp %g1,119 - be,a linux_syscall_for_solaris - mov 2, %g1 -1: - SAVE_ALL_HEAD - rd %wim, %l3 - - wr %l0, PSR_ET, %psr - nop - nop - mov %i0, %l5 - - call do_solaris_syscall - add %sp, STACKFRAME_SZ, %o0 - - st %o0, [%sp + STACKFRAME_SZ + PT_I0] - set PSR_C, %g2 - cmp %o0, -ERESTART_RESTARTBLOCK - bgeu 1f - ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 - - /* System call success, clear Carry condition code. */ - andn %g3, %g2, %g3 - clr %l6 - b 2f - st %g3, [%sp + STACKFRAME_SZ + PT_PSR] - -1: - /* System call failure, set Carry condition code. - * Also, get abs(errno) to return to the process. - */ - sub %g0, %o0, %o0 - mov 1, %l6 - st %o0, [%sp + STACKFRAME_SZ + PT_I0] - or %g3, %g2, %g3 - st %g3, [%sp + STACKFRAME_SZ + PT_PSR] - - /* Advance the pc and npc over the trap instruction. - * If the npc is unaligned (has a 1 in the lower byte), it means - * the kernel does not want us to play magic (ie, skipping over - * traps). Mainly when the Solaris code wants to set some PC and - * nPC (setcontext). - */ -2: - ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */ - andcc %l1, 1, %g0 - bne 1f - add %l1, 0x4, %l2 /* npc = npc+4 */ - st %l1, [%sp + STACKFRAME_SZ + PT_PC] - b ret_trap_entry - st %l2, [%sp + STACKFRAME_SZ + PT_NPC] - - /* kernel knows what it is doing, fixup npc and continue */ -1: - sub %l1, 1, %l1 - b ret_trap_entry - st %l1, [%sp + STACKFRAME_SZ + PT_NPC] - -#ifndef CONFIG_SUNOS_EMUL - .align 4 - .globl sunos_syscall -sunos_syscall: - SAVE_ALL_HEAD - rd %wim, %l3 - wr %l0, PSR_ET, %psr - nop - nop - mov %i0, %l5 - call do_sunos_syscall - add %sp, STACKFRAME_SZ, %o0 -#endif - - /* {net, open}bsd system calls enter here... */ - .align 4 - .globl bsd_syscall -bsd_syscall: - /* Direct access to user regs, must faster. */ - cmp %g1, NR_SYSCALLS - blu,a 1f - sll %g1, 2, %l4 - - set sys_ni_syscall, %l7 - b bsd_is_too_hard - nop - -1: - ld [%l7 + %l4], %l7 - - .globl bsd_is_too_hard -bsd_is_too_hard: - rd %wim, %l3 - SAVE_ALL - - wr %l0, PSR_ET, %psr - WRITE_PAUSE - -2: - mov %i0, %o0 - mov %i1, %o1 - mov %i2, %o2 - mov %i0, %l5 - mov %i3, %o3 - mov %i4, %o4 - call %l7 - mov %i5, %o5 - - st %o0, [%sp + STACKFRAME_SZ + PT_I0] - set PSR_C, %g2 - cmp %o0, -ERESTART_RESTARTBLOCK - bgeu 1f - ld [%sp + STACKFRAME_SZ + PT_PSR], %g3 - - /* System call success, clear Carry condition code. */ - andn %g3, %g2, %g3 - clr %l6 - b 2f - st %g3, [%sp + STACKFRAME_SZ + PT_PSR] - -1: - /* System call failure, set Carry condition code. - * Also, get abs(errno) to return to the process. - */ - sub %g0, %o0, %o0 -#if 0 /* XXX todo XXX */ - sethi %hi(bsd_xlatb_rorl), %o3 - or %o3, %lo(bsd_xlatb_rorl), %o3 - sll %o0, 2, %o0 - ld [%o3 + %o0], %o0 -#endif - mov 1, %l6 - st %o0, [%sp + STACKFRAME_SZ + PT_I0] - or %g3, %g2, %g3 - st %g3, [%sp + STACKFRAME_SZ + PT_PSR] - - /* Advance the pc and npc over the trap instruction. */ -2: - ld [%sp + STACKFRAME_SZ + PT_NPC], %l1 /* pc = npc */ - add %l1, 0x4, %l2 /* npc = npc+4 */ - st %l1, [%sp + STACKFRAME_SZ + PT_PC] - b ret_trap_entry - st %l2, [%sp + STACKFRAME_SZ + PT_NPC] - /* Saving and restoring the FPU state is best done from lowlevel code. * * void fpsave(unsigned long *fpregs, unsigned long *fsr, diff --git a/arch/sparc/kernel/errtbls.c b/arch/sparc/kernel/errtbls.c deleted file mode 100644 index ed14df7116e9..000000000000 --- a/arch/sparc/kernel/errtbls.c +++ /dev/null @@ -1,144 +0,0 @@ -/* errtbls.c: Error number conversion tables. - * - * Copyright (C) 1995, 2007 David S. Miller (davem@davemloft.net) - * - * Based upon preliminary work which is: - * - * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) - */ - -#include /* Solaris errnos */ - -/* Here is the table which converts between Linux error number values - * to the equivalent under Solaris. Note that since the Linux ones - * have been set up to match exactly those of SunOS, no translation - * table is needed for that OS. - */ - -int solaris_errno[] = { - 0, - SOL_EPERM, - SOL_ENOENT, - SOL_ESRCH, - SOL_EINTR, - SOL_EIO, - SOL_ENXIO, - SOL_E2BIG, - SOL_ENOEXEC, - SOL_EBADF, - SOL_ECHILD, - SOL_EAGAIN, - SOL_ENOMEM, - SOL_EACCES, - SOL_EFAULT, - SOL_NOTBLK, - SOL_EBUSY, - SOL_EEXIST, - SOL_EXDEV, - SOL_ENODEV, - SOL_ENOTDIR, - SOL_EISDIR, - SOL_EINVAL, - SOL_ENFILE, - SOL_EMFILE, - SOL_ENOTTY, - SOL_ETXTBSY, - SOL_EFBIG, - SOL_ENOSPC, - SOL_ESPIPE, - SOL_EROFS, - SOL_EMLINK, - SOL_EPIPE, - SOL_EDOM, - SOL_ERANGE, - SOL_EWOULDBLOCK, - SOL_EINPROGRESS, - SOL_EALREADY, - SOL_ENOTSOCK, - SOL_EDESTADDRREQ, - SOL_EMSGSIZE, - SOL_EPROTOTYPE, - SOL_ENOPROTOOPT, - SOL_EPROTONOSUPPORT, - SOL_ESOCKTNOSUPPORT, - SOL_EOPNOTSUPP, - SOL_EPFNOSUPPORT, - SOL_EAFNOSUPPORT, - SOL_EADDRINUSE, - SOL_EADDRNOTAVAIL, - SOL_ENETDOWN, - SOL_ENETUNREACH, - SOL_ENETRESET, - SOL_ECONNABORTED, - SOL_ECONNRESET, - SOL_ENOBUFS, - SOL_EISCONN, - SOL_ENOTONN, - SOL_ESHUTDOWN, - SOL_ETOOMANYREFS, - SOL_ETIMEDOUT, - SOL_ECONNREFUSED, - SOL_ELOOP, - SOL_ENAMETOOLONG, - SOL_EHOSTDOWN, - SOL_EHOSTUNREACH, - SOL_ENOTEMPTY, - SOL_EPROCLIM, - SOL_EUSERS, - SOL_EDQUOT, - SOL_ESTALE, - SOL_EREMOTE, - SOL_ENOSTR, - SOL_ETIME, - SOL_ENOSR, - SOL_ENOMSG, - SOL_EBADMSG, - SOL_IDRM, - SOL_EDEADLK, - SOL_ENOLCK, - SOL_ENONET, - SOL_ERREMOTE, - SOL_ENOLINK, - SOL_EADV, - SOL_ESRMNT, - SOL_ECOMM, - SOL_EPROTO, - SOL_EMULTIHOP, - SOL_EINVAL, /* EDOTDOT XXX??? */ - SOL_REMCHG, - SOL_NOSYS, - SOL_STRPIPE, - SOL_EOVERFLOW, - SOL_EBADFD, - SOL_ECHRNG, - SOL_EL2NSYNC, - SOL_EL3HLT, - SOL_EL3RST, - SOL_NRNG, - SOL_EUNATCH, - SOL_ENOCSI, - SOL_EL2HLT, - SOL_EBADE, - SOL_EBADR, - SOL_EXFULL, - SOL_ENOANO, - SOL_EBADRQC, - SOL_EBADSLT, - SOL_EDEADLOCK, - SOL_EBFONT, - SOL_ELIBEXEC, - SOL_ENODATA, - SOL_ELIBBAD, - SOL_ENOPKG, - SOL_ELIBACC, - SOL_ENOTUNIQ, - SOL_ERESTART, - SOL_EUCLEAN, - SOL_ENOTNAM, - SOL_ENAVAIL, - SOL_EISNAM, - SOL_EREMOTEIO, - SOL_EILSEQ, - SOL_ELIBMAX, - SOL_ELIBSCN, -}; diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 9a219e8b5ddb..b7f1e81c8ff2 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S @@ -78,11 +78,6 @@ sun4e_notsup: .asciz "Sparc-Linux sun4e support does not exist\n\n" .align 4 -#ifndef CONFIG_SUNOS_EMUL -#undef SUNOS_SYSCALL_TRAP -#define SUNOS_SYSCALL_TRAP SUNOS_NO_SYSCALL_TRAP -#endif - /* The Sparc trap table, bootloader gives us control at _start. */ .text .globl start, _stext, _start, __stext @@ -158,7 +153,7 @@ t_bad6f:BAD_TRAP(0x6f) BAD_TRAP(0x70) BAD_TRAP(0x71) BAD_TRAP(0x72) BAD_TRAP(0x7 t_bad74:BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78) t_bad79:BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d) t_bad7e:BAD_TRAP(0x7e) BAD_TRAP(0x7f) -t_sunos:SUNOS_SYSCALL_TRAP /* SunOS System Call */ +t_bad80:BAD_TRAP(0x80) /* SunOS System Call */ t_sbkpt:BREAKPOINT_TRAP /* Software Breakpoint/KGDB */ t_divz: TRAP_ENTRY(0x82, do_hw_divzero) /* Divide by zero trap */ t_flwin:TRAP_ENTRY(0x83, do_flush_windows) /* Flush Windows Trap */ @@ -166,8 +161,8 @@ t_clwin:BAD_TRAP(0x84) /* Clean Windows Trap */ t_rchk: BAD_TRAP(0x85) /* Range Check */ t_funal:BAD_TRAP(0x86) /* Fix Unaligned Access Trap */ t_iovf: BAD_TRAP(0x87) /* Integer Overflow Trap */ -t_slowl:SOLARIS_SYSCALL_TRAP /* Slowaris System Call */ -t_netbs:NETBSD_SYSCALL_TRAP /* Net-B.S. System Call */ +t_bad88:BAD_TRAP(0x88) /* Slowaris System Call */ +t_bad89:BAD_TRAP(0x89) /* Net-B.S. System Call */ t_bad8a:BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e) t_bad8f:BAD_TRAP(0x8f) t_linux:LINUX_SYSCALL_TRAP /* Linux System Call */ @@ -178,7 +173,7 @@ t_getcc:GETCC_TRAP /* Get Condition Codes */ t_setcc:SETCC_TRAP /* Set Condition Codes */ t_getpsr:GETPSR_TRAP /* Get PSR Register */ t_bada3:BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) -t_slowi:INDIRECT_SOLARIS_SYSCALL(156) +t_bada7:BAD_TRAP(0xa7) t_bada8:BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) t_badac:BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) t_badb1:BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) @@ -243,19 +238,19 @@ trapbase_cpu1: BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78) BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d) BAD_TRAP(0x7e) BAD_TRAP(0x7f) - SUNOS_SYSCALL_TRAP + BAD_TRAP(0x80) BREAKPOINT_TRAP TRAP_ENTRY(0x82, do_hw_divzero) TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85) - BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP - NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) + BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88) + BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f) LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) - INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) + BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba) @@ -311,19 +306,19 @@ trapbase_cpu2: BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78) BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d) BAD_TRAP(0x7e) BAD_TRAP(0x7f) - SUNOS_SYSCALL_TRAP + BAD_TRAP(0x80) BREAKPOINT_TRAP TRAP_ENTRY(0x82, do_hw_divzero) TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85) - BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP - NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) + BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88) + BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f) LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) - INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) + BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba) @@ -379,19 +374,19 @@ trapbase_cpu3: BAD_TRAP(0x74) BAD_TRAP(0x75) BAD_TRAP(0x76) BAD_TRAP(0x77) BAD_TRAP(0x78) BAD_TRAP(0x79) BAD_TRAP(0x7a) BAD_TRAP(0x7b) BAD_TRAP(0x7c) BAD_TRAP(0x7d) BAD_TRAP(0x7e) BAD_TRAP(0x7f) - SUNOS_SYSCALL_TRAP + BAD_TRAP(0x80) BREAKPOINT_TRAP TRAP_ENTRY(0x82, do_hw_divzero) TRAP_ENTRY(0x83, do_flush_windows) BAD_TRAP(0x84) BAD_TRAP(0x85) - BAD_TRAP(0x86) BAD_TRAP(0x87) SOLARIS_SYSCALL_TRAP - NETBSD_SYSCALL_TRAP BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) + BAD_TRAP(0x86) BAD_TRAP(0x87) BAD_TRAP(0x88) + BAD_TRAP(0x89) BAD_TRAP(0x8a) BAD_TRAP(0x8b) BAD_TRAP(0x8c) BAD_TRAP(0x8d) BAD_TRAP(0x8e) BAD_TRAP(0x8f) LINUX_SYSCALL_TRAP BAD_TRAP(0x91) BAD_TRAP(0x92) BAD_TRAP(0x93) BAD_TRAP(0x94) BAD_TRAP(0x95) BAD_TRAP(0x96) BAD_TRAP(0x97) BAD_TRAP(0x98) BAD_TRAP(0x99) BAD_TRAP(0x9a) BAD_TRAP(0x9b) BAD_TRAP(0x9c) BAD_TRAP(0x9d) BAD_TRAP(0x9e) BAD_TRAP(0x9f) GETCC_TRAP SETCC_TRAP GETPSR_TRAP BAD_TRAP(0xa3) BAD_TRAP(0xa4) BAD_TRAP(0xa5) BAD_TRAP(0xa6) - INDIRECT_SOLARIS_SYSCALL(156) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) + BAD_TRAP(0xa7) BAD_TRAP(0xa8) BAD_TRAP(0xa9) BAD_TRAP(0xaa) BAD_TRAP(0xab) BAD_TRAP(0xac) BAD_TRAP(0xad) BAD_TRAP(0xae) BAD_TRAP(0xaf) BAD_TRAP(0xb0) BAD_TRAP(0xb1) BAD_TRAP(0xb2) BAD_TRAP(0xb3) BAD_TRAP(0xb4) BAD_TRAP(0xb5) BAD_TRAP(0xb6) BAD_TRAP(0xb7) BAD_TRAP(0xb8) BAD_TRAP(0xb9) BAD_TRAP(0xba) diff --git a/arch/sparc/kernel/sclow.S b/arch/sparc/kernel/sclow.S deleted file mode 100644 index 136e37c53d49..000000000000 --- a/arch/sparc/kernel/sclow.S +++ /dev/null @@ -1,86 +0,0 @@ -/* sclow.S: Low level special syscall handling. - * Basically these are cases where we can completely - * handle the system call without saving any state - * because we know that the process will not sleep. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - */ - -#include -#include -#include -#include -#include -#include -#include - -#define CC_AND_RETT \ - set PSR_C, %l4; \ - andn %l0, %l4, %l4; \ - wr %l4, 0x0, %psr; \ - nop; nop; nop; \ - jmp %l2; \ - rett %l2 + 4; - -#define SC_AND_RETT \ - set PSR_C, %l4; \ - or %l0, %l4, %l4; \ - wr %l4, 0x0, %psr; \ - nop; nop; nop; \ - jmp %l2; \ - rett %l2 + 4; - -#define LABEL(func) func##_low - - .globl LABEL(sunosnop) -LABEL(sunosnop): - CC_AND_RETT - -#if (ASIZ_task_uid == 2 && ASIZ_task_euid == 2) - .globl LABEL(sunosgetuid) -LABEL(sunosgetuid): - LOAD_CURRENT(l4, l5) - ld [%l4 + TI_TASK], %l4 - lduh [%l4 + AOFF_task_uid], %i0 - lduh [%l4 + AOFF_task_euid], %i1 - CC_AND_RETT -#endif - -#if (ASIZ_task_gid == 2 && ASIZ_task_egid == 2) - .globl LABEL(sunosgetgid) -LABEL(sunosgetgid): - LOAD_CURRENT(l4, l5) - ld [%l4 + TI_TASK], %l4 - lduh [%l4 + AOFF_task_gid], %i0 - lduh [%l4 + AOFF_task_egid], %i1 - CC_AND_RETT -#endif - - .globl LABEL(sunosmctl) -LABEL(sunosmctl): - mov 0, %i0 - CC_AND_RETT - - .globl LABEL(sunosgdtsize) -LABEL(sunosgdtsize): - mov 256, %i0 - CC_AND_RETT - - .globl LABEL(getpagesize) -LABEL(getpagesize): - set PAGE_SIZE, %i0 - CC_AND_RETT - - /* XXX sys_nice() XXX */ - /* XXX sys_setpriority() XXX */ - /* XXX sys_getpriority() XXX */ - /* XXX sys_setregid() XXX */ - /* XXX sys_setgid() XXX */ - /* XXX sys_setreuid() XXX */ - /* XXX sys_setuid() XXX */ - /* XXX sys_setfsuid() XXX */ - /* XXX sys_setfsgid() XXX */ - /* XXX sys_setpgid() XXX */ - /* XXX sys_getpgid() XXX */ - /* XXX sys_setsid() XXX */ - /* XXX sys_getsid() XXX */ diff --git a/arch/sparc/kernel/signal.c b/arch/sparc/kernel/signal.c index 9994cac95078..1f730619a24a 100644 --- a/arch/sparc/kernel/signal.c +++ b/arch/sparc/kernel/signal.c @@ -22,7 +22,6 @@ #include #include -#include #include #include #include /* flush_sig_insns */ @@ -454,7 +453,6 @@ setup_frame(struct sigaction *sa, struct pt_regs *regs, int signr, sigset_t *old break; case SIGSYS: if (info->si_code == (__SI_FAULT|0x100)) { - /* See sys_sunos.c */ sig_code = info->si_trapno; break; } @@ -676,291 +674,17 @@ sigsegv: force_sigsegv(signo, current); } -/* Setup a Solaris stack frame */ -static inline void -setup_svr4_frame(struct sigaction *sa, unsigned long pc, unsigned long npc, - struct pt_regs *regs, int signr, sigset_t *oldset) -{ - svr4_signal_frame_t __user *sfp; - svr4_gregset_t __user *gr; - svr4_siginfo_t __user *si; - svr4_mcontext_t __user *mc; - svr4_gwindows_t __user *gw; - svr4_ucontext_t __user *uc; - svr4_sigset_t setv; - struct thread_info *tp = current_thread_info(); - int window = 0, err; - - synchronize_user_stack(); - sfp = (svr4_signal_frame_t __user *) - get_sigframe(sa, regs, SVR4_SF_ALIGNED + sizeof(struct reg_window)); - - if (invalid_frame_pointer(sfp, sizeof(*sfp))) - goto sigill_and_return; - - /* Start with a clean frame pointer and fill it */ - err = __clear_user(sfp, sizeof(*sfp)); - - /* Setup convenience variables */ - si = &sfp->si; - uc = &sfp->uc; - gw = &sfp->gw; - mc = &uc->mcontext; - gr = &mc->greg; - - /* FIXME: where am I supposed to put this? - * sc->sigc_onstack = old_status; - * anyways, it does not look like it is used for anything at all. - */ - setv.sigbits[0] = oldset->sig[0]; - setv.sigbits[1] = oldset->sig[1]; - if (_NSIG_WORDS >= 4) { - setv.sigbits[2] = oldset->sig[2]; - setv.sigbits[3] = oldset->sig[3]; - err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); - } else - err |= __copy_to_user(&uc->sigmask, &setv, - 2 * sizeof(unsigned int)); - - /* Store registers */ - err |= __put_user(regs->pc, &((*gr)[SVR4_PC])); - err |= __put_user(regs->npc, &((*gr)[SVR4_NPC])); - err |= __put_user(regs->psr, &((*gr)[SVR4_PSR])); - err |= __put_user(regs->y, &((*gr)[SVR4_Y])); - - /* Copy g[1..7] and o[0..7] registers */ - err |= __copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs[UREG_G1], - sizeof(long) * 7); - err |= __copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs[UREG_I0], - sizeof(long) * 8); - - /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &uc->stack.sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - err |= __put_user(current->sas_ss_size, &uc->stack.size); - - /* Save the currently window file: */ - - /* 1. Link sfp->uc->gwins to our windows */ - err |= __put_user(gw, &mc->gwin); - - /* 2. Number of windows to restore at setcontext(): */ - err |= __put_user(tp->w_saved, &gw->count); - - /* 3. Save each valid window - * Currently, it makes a copy of the windows from the kernel copy. - * David's code for SunOS, makes the copy but keeps the pointer to - * the kernel. My version makes the pointer point to a userland - * copy of those. Mhm, I wonder if I shouldn't just ignore those - * on setcontext and use those that are on the kernel, the signal - * handler should not be modyfing those, mhm. - * - * These windows are just used in case synchronize_user_stack failed - * to flush the user windows. - */ - for (window = 0; window < tp->w_saved; window++) { - err |= __put_user((int __user *) &(gw->win[window]), &gw->winptr[window]); - err |= __copy_to_user(&gw->win[window], - &tp->reg_window[window], - sizeof(svr4_rwindow_t)); - err |= __put_user(0, gw->winptr[window]); - } - - /* 4. We just pay attention to the gw->count field on setcontext */ - tp->w_saved = 0; /* So process is allowed to execute. */ - - /* Setup the signal information. Solaris expects a bunch of - * information to be passed to the signal handler, we don't provide - * that much currently, should use siginfo. - */ - err |= __put_user(signr, &si->siginfo.signo); - err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); - if (err) - goto sigsegv; - - regs->u_regs[UREG_FP] = (unsigned long) sfp; - regs->pc = (unsigned long) sa->sa_handler; - regs->npc = (regs->pc + 4); - - /* Arguments passed to signal handler */ - if (regs->u_regs[14]){ - struct reg_window __user *rw = (struct reg_window __user *) - regs->u_regs[14]; - - err |= __put_user(signr, &rw->ins[0]); - err |= __put_user(si, &rw->ins[1]); - err |= __put_user(uc, &rw->ins[2]); - err |= __put_user(sfp, &rw->ins[6]); /* frame pointer */ - if (err) - goto sigsegv; - - regs->u_regs[UREG_I0] = signr; - regs->u_regs[UREG_I1] = (unsigned long) si; - regs->u_regs[UREG_I2] = (unsigned long) uc; - } - return; - -sigill_and_return: - do_exit(SIGILL); -sigsegv: - force_sigsegv(signr, current); -} - -asmlinkage int svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs) -{ - svr4_gregset_t __user *gr; - svr4_mcontext_t __user *mc; - svr4_sigset_t setv; - int err = 0; - - synchronize_user_stack(); - - if (current_thread_info()->w_saved) - return -EFAULT; - - err = clear_user(uc, sizeof(*uc)); - if (err) - return -EFAULT; - - /* Setup convenience variables */ - mc = &uc->mcontext; - gr = &mc->greg; - - setv.sigbits[0] = current->blocked.sig[0]; - setv.sigbits[1] = current->blocked.sig[1]; - if (_NSIG_WORDS >= 4) { - setv.sigbits[2] = current->blocked.sig[2]; - setv.sigbits[3] = current->blocked.sig[3]; - err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); - } else - err |= __copy_to_user(&uc->sigmask, &setv, - 2 * sizeof(unsigned int)); - - /* Store registers */ - err |= __put_user(regs->pc, &uc->mcontext.greg[SVR4_PC]); - err |= __put_user(regs->npc, &uc->mcontext.greg[SVR4_NPC]); - err |= __put_user(regs->psr, &uc->mcontext.greg[SVR4_PSR]); - err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]); - - /* Copy g[1..7] and o[0..7] registers */ - err |= __copy_to_user(&(*gr)[SVR4_G1], ®s->u_regs[UREG_G1], - sizeof(uint) * 7); - err |= __copy_to_user(&(*gr)[SVR4_O0], ®s->u_regs[UREG_I0], - sizeof(uint) * 8); - - /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &uc->stack.sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - err |= __put_user(current->sas_ss_size, &uc->stack.size); - - /* The register file is not saved - * we have already stuffed all of it with sync_user_stack - */ - return (err ? -EFAULT : 0); -} - -/* Set the context for a svr4 application, this is Solaris way to sigreturn */ -asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs) -{ - svr4_gregset_t __user *gr; - unsigned long pc, npc, psr; - mm_segment_t old_fs; - sigset_t set; - svr4_sigset_t setv; - int err; - stack_t st; - - /* Fixme: restore windows, or is this already taken care of in - * svr4_setup_frame when sync_user_windows is done? - */ - flush_user_windows(); - - if (current_thread_info()->w_saved) - goto sigsegv_and_return; - - if (((unsigned long) c) & 3) - goto sigsegv_and_return; - - if (!__access_ok((unsigned long)c, sizeof(*c))) - goto sigsegv_and_return; - - /* Check for valid PC and nPC */ - gr = &c->mcontext.greg; - err = __get_user(pc, &((*gr)[SVR4_PC])); - err |= __get_user(npc, &((*gr)[SVR4_NPC])); - - if ((pc | npc) & 3) - goto sigsegv_and_return; - - /* Retrieve information from passed ucontext */ - /* note that nPC is ored a 1, this is used to inform entry.S */ - /* that we don't want it to mess with our PC and nPC */ - - /* This is pretty much atomic, no amount locking would prevent - * the races which exist anyways. - */ - err |= __copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t)); - - err |= __get_user(st.ss_sp, &c->stack.sp); - err |= __get_user(st.ss_flags, &c->stack.flags); - err |= __get_user(st.ss_size, &c->stack.size); - - if (err) - goto sigsegv_and_return; - - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack((const stack_t __user *) &st, NULL, - regs->u_regs[UREG_I6]); - set_fs(old_fs); - - set.sig[0] = setv.sigbits[0]; - set.sig[1] = setv.sigbits[1]; - if (_NSIG_WORDS >= 4) { - set.sig[2] = setv.sigbits[2]; - set.sig[3] = setv.sigbits[3]; - } - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - regs->pc = pc; - regs->npc = npc | 1; - err |= __get_user(regs->y, &((*gr)[SVR4_Y])); - err |= __get_user(psr, &((*gr)[SVR4_PSR])); - regs->psr &= ~(PSR_ICC); - regs->psr |= (psr & PSR_ICC); - - /* Restore g[1..7] and o[0..7] registers */ - err |= __copy_from_user(®s->u_regs[UREG_G1], &(*gr)[SVR4_G1], - sizeof(long) * 7); - err |= __copy_from_user(®s->u_regs[UREG_I0], &(*gr)[SVR4_O0], - sizeof(long) * 8); - return (err ? -EFAULT : 0); - -sigsegv_and_return: - force_sig(SIGSEGV, current); - return -EFAULT; -} - static inline void handle_signal(unsigned long signr, struct k_sigaction *ka, - siginfo_t *info, sigset_t *oldset, struct pt_regs *regs, - int svr4_signal) + siginfo_t *info, sigset_t *oldset, struct pt_regs *regs) { - if (svr4_signal) - setup_svr4_frame(&ka->sa, regs->pc, regs->npc, regs, signr, oldset); - else { - if (ka->sa.sa_flags & SA_SIGINFO) - new_setup_rt_frame(ka, regs, signr, oldset, info); - else if (current->thread.new_signal) - new_setup_frame(ka, regs, signr, oldset); - else - setup_frame(&ka->sa, regs, signr, oldset, info); - } + if (ka->sa.sa_flags & SA_SIGINFO) + new_setup_rt_frame(ka, regs, signr, oldset, info); + else if (current->thread.new_signal) + new_setup_frame(ka, regs, signr, oldset); + else + setup_frame(&ka->sa, regs, signr, oldset, info); + spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NOMASK)) @@ -1002,17 +726,6 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest int signr; sigset_t *oldset; - /* - * XXX Disable svr4 signal handling until solaris emulation works. - * It is buggy - Anton - */ -#define SVR4_SIGNAL_BROKEN 1 -#ifdef SVR4_SIGNAL_BROKEN - int svr4_signal = 0; -#else - int svr4_signal = current->personality == PER_SVR4; -#endif - cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; @@ -1025,8 +738,8 @@ asmlinkage void do_signal(struct pt_regs * regs, unsigned long orig_i0, int rest if (signr > 0) { if (cookie.restart_syscall) syscall_restart(cookie.orig_i0, regs, &ka.sa); - handle_signal(signr, &ka, &info, oldset, - regs, svr4_signal); + handle_signal(signr, &ka, &info, oldset, regs); + /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, * and will be restored by sigreturn, so we can simply diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index 97b1de0e9094..0bcf98a7ef38 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c @@ -36,12 +36,10 @@ #include #include #include -#include #include #include #include #include -#include #include #include #ifdef CONFIG_SBUS @@ -62,8 +60,6 @@ struct poll { short revents; }; -extern int svr4_getcontext (svr4_ucontext_t *, struct pt_regs *); -extern int svr4_setcontext (svr4_ucontext_t *, struct pt_regs *); extern void (*__copy_1page)(void *, const void *); extern void __memmove(void *, const void *, __kernel_size_t); extern void (*bzero_1page)(void *); @@ -204,10 +200,6 @@ EXPORT_SYMBOL(kmap_atomic); EXPORT_SYMBOL(kunmap_atomic); #endif -/* Solaris/SunOS binary compatibility */ -EXPORT_SYMBOL(svr4_setcontext); -EXPORT_SYMBOL(svr4_getcontext); - /* prom symbols */ EXPORT_SYMBOL(idprom); EXPORT_SYMBOL(prom_root_node); diff --git a/arch/sparc/kernel/sunos_asm.S b/arch/sparc/kernel/sunos_asm.S deleted file mode 100644 index 07fe86014fb5..000000000000 --- a/arch/sparc/kernel/sunos_asm.S +++ /dev/null @@ -1,67 +0,0 @@ -/* $Id: sunos_asm.S,v 1.15 2000/01/11 17:33:21 jj Exp $ - * sunos_asm.S: SunOS system calls which must have a low-level - * entry point to operate correctly. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * - * Based upon preliminary work which is: - * - * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) - */ - -#include - - .text - .align 4 - - /* When calling ret_sys_call, %o0 should contain the same - * value as in [%sp + STACKFRAME_SZ + PT_I0] */ - - /* SunOS getpid() returns pid in %o0 and ppid in %o1 */ - .globl sunos_getpid -sunos_getpid: - call sys_getppid - nop - - call sys_getpid - st %o0, [%sp + STACKFRAME_SZ + PT_I1] - - b ret_sys_call - st %o0, [%sp + STACKFRAME_SZ + PT_I0] - - /* SunOS getuid() returns uid in %o0 and euid in %o1 */ - .globl sunos_getuid -sunos_getuid: - call sys_geteuid16 - nop - - call sys_getuid16 - st %o0, [%sp + STACKFRAME_SZ + PT_I1] - - b ret_sys_call - st %o0, [%sp + STACKFRAME_SZ + PT_I0] - - /* SunOS getgid() returns gid in %o0 and egid in %o1 */ - .globl sunos_getgid -sunos_getgid: - call sys_getegid16 - nop - - call sys_getgid16 - st %o0, [%sp + STACKFRAME_SZ + PT_I1] - - b ret_sys_call - st %o0, [%sp + STACKFRAME_SZ + PT_I0] - - /* SunOS's execv() call only specifies the argv argument, the - * environment settings are the same as the calling processes. - */ - .globl sunos_execv -sunos_execv: - st %g0, [%sp + STACKFRAME_SZ + PT_I2] - - call sparc_execve - add %sp, STACKFRAME_SZ, %o0 - - b ret_sys_call - ld [%sp + STACKFRAME_SZ + PT_I0], %o0 diff --git a/arch/sparc/kernel/sunos_ioctl.c b/arch/sparc/kernel/sunos_ioctl.c deleted file mode 100644 index e613cc6a10ba..000000000000 --- a/arch/sparc/kernel/sunos_ioctl.c +++ /dev/null @@ -1,230 +0,0 @@ -/* $Id: sunos_ioctl.c,v 1.34 2000/09/03 14:10:56 anton Exp $ - * sunos_ioctl.c: The Linux Operating system: SunOS ioctl compatibility. - * - * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -extern char sunkbd_type; -extern char sunkbd_layout; -#endif - -/* NR_OPEN is now larger and dynamic in recent kernels. */ -#define SUNOS_NR_OPEN 256 - -asmlinkage int sunos_ioctl (int fd, unsigned long cmd, unsigned long arg) -{ - int ret = -EBADF; - - if (fd >= SUNOS_NR_OPEN || !fcheck(fd)) - goto out; - - /* First handle an easy compat. case for tty ldisc. */ - if (cmd == TIOCSETD) { - int __user *p; - int ntty = N_TTY, tmp; - mm_segment_t oldfs; - - p = (int __user *) arg; - ret = -EFAULT; - if (get_user(tmp, p)) - goto out; - if (tmp == 2) { - oldfs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long) &ntty); - set_fs(oldfs); - ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); - goto out; - } - } - - /* Binary compatibility is good American knowhow fuckin' up. */ - if (cmd == TIOCNOTTY) { - ret = sys_setsid(); - goto out; - } - - /* SunOS networking ioctls. */ - switch (cmd) { - case _IOW('r', 10, struct rtentry): - ret = sys_ioctl(fd, SIOCADDRT, arg); - goto out; - case _IOW('r', 11, struct rtentry): - ret = sys_ioctl(fd, SIOCDELRT, arg); - goto out; - case _IOW('i', 12, struct ifreq): - ret = sys_ioctl(fd, SIOCSIFADDR, arg); - goto out; - case _IOWR('i', 13, struct ifreq): - ret = sys_ioctl(fd, SIOCGIFADDR, arg); - goto out; - case _IOW('i', 14, struct ifreq): - ret = sys_ioctl(fd, SIOCSIFDSTADDR, arg); - goto out; - case _IOWR('i', 15, struct ifreq): - ret = sys_ioctl(fd, SIOCGIFDSTADDR, arg); - goto out; - case _IOW('i', 16, struct ifreq): - ret = sys_ioctl(fd, SIOCSIFFLAGS, arg); - goto out; - case _IOWR('i', 17, struct ifreq): - ret = sys_ioctl(fd, SIOCGIFFLAGS, arg); - goto out; - case _IOW('i', 18, struct ifreq): - ret = sys_ioctl(fd, SIOCSIFMEM, arg); - goto out; - case _IOWR('i', 19, struct ifreq): - ret = sys_ioctl(fd, SIOCGIFMEM, arg); - goto out; - case _IOWR('i', 20, struct ifconf): - ret = sys_ioctl(fd, SIOCGIFCONF, arg); - goto out; - case _IOW('i', 21, struct ifreq): /* SIOCSIFMTU */ - ret = sys_ioctl(fd, SIOCSIFMTU, arg); - goto out; - case _IOWR('i', 22, struct ifreq): /* SIOCGIFMTU */ - ret = sys_ioctl(fd, SIOCGIFMTU, arg); - goto out; - - case _IOWR('i', 23, struct ifreq): - ret = sys_ioctl(fd, SIOCGIFBRDADDR, arg); - goto out; - case _IOW('i', 24, struct ifreq): - ret = sys_ioctl(fd, SIOCSIFBRDADDR, arg); - goto out; - case _IOWR('i', 25, struct ifreq): - ret = sys_ioctl(fd, SIOCGIFNETMASK, arg); - goto out; - case _IOW('i', 26, struct ifreq): - ret = sys_ioctl(fd, SIOCSIFNETMASK, arg); - goto out; - case _IOWR('i', 27, struct ifreq): - ret = sys_ioctl(fd, SIOCGIFMETRIC, arg); - goto out; - case _IOW('i', 28, struct ifreq): - ret = sys_ioctl(fd, SIOCSIFMETRIC, arg); - goto out; - - case _IOW('i', 30, struct arpreq): - ret = sys_ioctl(fd, SIOCSARP, arg); - goto out; - case _IOWR('i', 31, struct arpreq): - ret = sys_ioctl(fd, SIOCGARP, arg); - goto out; - case _IOW('i', 32, struct arpreq): - ret = sys_ioctl(fd, SIOCDARP, arg); - goto out; - - case _IOW('i', 40, struct ifreq): /* SIOCUPPER */ - case _IOW('i', 41, struct ifreq): /* SIOCLOWER */ - case _IOW('i', 44, struct ifreq): /* SIOCSETSYNC */ - case _IOW('i', 45, struct ifreq): /* SIOCGETSYNC */ - case _IOW('i', 46, struct ifreq): /* SIOCSSDSTATS */ - case _IOW('i', 47, struct ifreq): /* SIOCSSESTATS */ - case _IOW('i', 48, struct ifreq): /* SIOCSPROMISC */ - ret = -EOPNOTSUPP; - goto out; - - case _IOW('i', 49, struct ifreq): - ret = sys_ioctl(fd, SIOCADDMULTI, arg); - goto out; - case _IOW('i', 50, struct ifreq): - ret = sys_ioctl(fd, SIOCDELMULTI, arg); - goto out; - - /* FDDI interface ioctls, unsupported. */ - - case _IOW('i', 51, struct ifreq): /* SIOCFDRESET */ - case _IOW('i', 52, struct ifreq): /* SIOCFDSLEEP */ - case _IOW('i', 53, struct ifreq): /* SIOCSTRTFMWAR */ - case _IOW('i', 54, struct ifreq): /* SIOCLDNSTRTFW */ - case _IOW('i', 55, struct ifreq): /* SIOCGETFDSTAT */ - case _IOW('i', 56, struct ifreq): /* SIOCFDNMIINT */ - case _IOW('i', 57, struct ifreq): /* SIOCFDEXUSER */ - case _IOW('i', 58, struct ifreq): /* SIOCFDGNETMAP */ - case _IOW('i', 59, struct ifreq): /* SIOCFDGIOCTL */ - printk("FDDI ioctl, returning EOPNOTSUPP\n"); - ret = -EOPNOTSUPP; - goto out; - - case _IOW('t', 125, int): - /* More stupid tty sunos ioctls, just - * say it worked. - */ - ret = 0; - goto out; - /* Non posix grp */ - case _IOW('t', 118, int): { - int oldval, newval, __user *ptr; - - cmd = TIOCSPGRP; - ptr = (int __user *) arg; - ret = -EFAULT; - if (get_user(oldval, ptr)) - goto out; - ret = sys_ioctl(fd, cmd, arg); - __get_user(newval, ptr); - if (newval == -1) { - __put_user(oldval, ptr); - ret = -EIO; - } - if (ret == -ENOTTY) - ret = -EIO; - goto out; - } - - case _IOR('t', 119, int): { - int oldval, newval, __user *ptr; - - cmd = TIOCGPGRP; - ptr = (int __user *) arg; - ret = -EFAULT; - if (get_user(oldval, ptr)) - goto out; - ret = sys_ioctl(fd, cmd, arg); - __get_user(newval, ptr); - if (newval == -1) { - __put_user(oldval, ptr); - ret = -EIO; - } - if (ret == -ENOTTY) - ret = -EIO; - goto out; - } - } - -#if 0 - if ((cmd & 0xff00) == ('k' << 8)) { - printk ("[[KBIO: %8.8x\n", (unsigned int) cmd); - } -#endif - - ret = sys_ioctl(fd, cmd, arg); - /* so stupid... */ - ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); -out: - return ret; -} - - diff --git a/arch/sparc/kernel/sys_solaris.c b/arch/sparc/kernel/sys_solaris.c deleted file mode 100644 index 2226a5992484..000000000000 --- a/arch/sparc/kernel/sys_solaris.c +++ /dev/null @@ -1,35 +0,0 @@ -/* - * linux/arch/sparc/kernel/sys_solaris.c - * - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -asmlinkage int -do_solaris_syscall (struct pt_regs *regs) -{ - static int cnt = 0; - if (++cnt < 10) printk ("No solaris handler\n"); - force_sig(SIGSEGV, current); - return 0; -} - -#ifndef CONFIG_SUNOS_EMUL -asmlinkage int -do_sunos_syscall (struct pt_regs *regs) -{ - static int cnt = 0; - if (++cnt < 10) printk ("SunOS binary emulation not compiled in\n"); - force_sig (SIGSEGV, current); - return 0; -} -#endif diff --git a/arch/sparc/kernel/sys_sunos.c b/arch/sparc/kernel/sys_sunos.c deleted file mode 100644 index f5b608bbe8af..000000000000 --- a/arch/sparc/kernel/sys_sunos.c +++ /dev/null @@ -1,1210 +0,0 @@ -/* $Id: sys_sunos.c,v 1.137 2002/02/08 03:57:14 davem Exp $ - * sys_sunos.c: SunOS specific syscall compatibility support. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) - * - * Based upon preliminary work which is: - * - * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#ifndef KERNEL_DS -#include -#endif - -#include -#include -#include -#include /* for gethostid() */ -#include -#include - -/* For the nfs mount emulation */ -#include -#include -#include -#include -#include - -/* for sunos_select */ -#include -#include - -/* NR_OPEN is now larger and dynamic in recent kernels. */ -#define SUNOS_NR_OPEN 256 - -/* We use the SunOS mmap() semantics. */ -asmlinkage unsigned long sunos_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long off) -{ - struct file * file = NULL; - unsigned long retval, ret_type; - - if (flags & MAP_NORESERVE) { - static int cnt; - if (cnt++ < 10) - printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n", - current->comm); - flags &= ~MAP_NORESERVE; - } - retval = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - if (fd >= SUNOS_NR_OPEN) - goto out; - file = fget(fd); - if (!file) - goto out; - } - - retval = -EINVAL; - /* If this is ld.so or a shared library doing an mmap - * of /dev/zero, transform it into an anonymous mapping. - * SunOS is so stupid some times... hmph! - */ - if (file) { - if (imajor(file->f_path.dentry->d_inode) == MEM_MAJOR && - iminor(file->f_path.dentry->d_inode) == 5) { - flags |= MAP_ANONYMOUS; - fput(file); - file = NULL; - } - } - ret_type = flags & _MAP_NEW; - flags &= ~_MAP_NEW; - - if (!(flags & MAP_FIXED)) - addr = 0; - else { - if (ARCH_SUN4C_SUN4 && - (len > 0x20000000 || - ((flags & MAP_FIXED) && - addr < 0xe0000000 && addr + len > 0x20000000))) - goto out_putf; - - /* See asm-sparc/uaccess.h */ - if (len > TASK_SIZE - PAGE_SIZE || - addr + len > TASK_SIZE - PAGE_SIZE) - goto out_putf; - } - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); - retval = do_mmap(file, addr, len, prot, flags, off); - up_write(¤t->mm->mmap_sem); - if (!ret_type) - retval = ((retval < PAGE_OFFSET) ? 0 : retval); - -out_putf: - if (file) - fput(file); -out: - return retval; -} - -/* lmbench calls this, just say "yeah, ok" */ -asmlinkage int sunos_mctl(unsigned long addr, unsigned long len, int function, char *arg) -{ - return 0; -} - -/* SunOS is completely broken... it returns 0 on success, otherwise - * ENOMEM. For sys_sbrk() it wants the old brk value as a return - * on success and ENOMEM as before on failure. - */ -asmlinkage int sunos_brk(unsigned long brk) -{ - int freepages, retval = -ENOMEM; - unsigned long rlim; - unsigned long newbrk, oldbrk; - - down_write(¤t->mm->mmap_sem); - if (ARCH_SUN4C_SUN4) { - if (brk >= 0x20000000 && brk < 0xe0000000) { - goto out; - } - } - - if (brk < current->mm->end_code) - goto out; - - newbrk = PAGE_ALIGN(brk); - oldbrk = PAGE_ALIGN(current->mm->brk); - retval = 0; - if (oldbrk == newbrk) { - current->mm->brk = brk; - goto out; - } - - /* - * Always allow shrinking brk - */ - if (brk <= current->mm->brk) { - current->mm->brk = brk; - do_munmap(current->mm, newbrk, oldbrk-newbrk); - goto out; - } - /* - * Check against rlimit and stack.. - */ - retval = -ENOMEM; - rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; - if (rlim >= RLIM_INFINITY) - rlim = ~0; - if (brk - current->mm->end_code > rlim) - goto out; - - /* - * Check against existing mmap mappings. - */ - if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE)) - goto out; - - /* - * stupid algorithm to decide if we have enough memory: while - * simple, it hopefully works in most obvious cases.. Easy to - * fool it, but this should catch most mistakes. - */ - freepages = global_page_state(NR_FILE_PAGES); - freepages >>= 1; - freepages += nr_free_pages(); - freepages += nr_swap_pages; - freepages -= num_physpages >> 4; - freepages -= (newbrk-oldbrk) >> PAGE_SHIFT; - if (freepages < 0) - goto out; - /* - * Ok, we have probably got enough memory - let it rip. - */ - current->mm->brk = brk; - do_brk(oldbrk, newbrk-oldbrk); - retval = 0; -out: - up_write(¤t->mm->mmap_sem); - return retval; -} - -asmlinkage unsigned long sunos_sbrk(int increment) -{ - int error; - unsigned long oldbrk; - - /* This should do it hopefully... */ - lock_kernel(); - oldbrk = current->mm->brk; - error = sunos_brk(((int) current->mm->brk) + increment); - if (!error) - error = oldbrk; - unlock_kernel(); - return error; -} - -/* XXX Completely undocumented, and completely magic... - * XXX I believe it is to increase the size of the stack by - * XXX argument 'increment' and return the new end of stack - * XXX area. Wheee... - */ -asmlinkage unsigned long sunos_sstk(int increment) -{ - lock_kernel(); - printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n", - current->comm, increment); - unlock_kernel(); - return -1; -} - -/* Give hints to the kernel as to what paging strategy to use... - * Completely bogus, don't remind me. - */ -#define VA_NORMAL 0 /* Normal vm usage expected */ -#define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */ -#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */ -#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */ -static char *vstrings[] = { - "VA_NORMAL", - "VA_ABNORMAL", - "VA_SEQUENTIAL", - "VA_INVALIDATE", -}; - -asmlinkage void sunos_vadvise(unsigned long strategy) -{ - /* I wanna see who uses this... */ - lock_kernel(); - printk("%s: Advises us to use %s paging strategy\n", - current->comm, - strategy <= 3 ? vstrings[strategy] : "BOGUS"); - unlock_kernel(); -} - -/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE - * resource limit and is for backwards compatibility with older sunos - * revs. - */ -asmlinkage long sunos_getdtablesize(void) -{ - return SUNOS_NR_OPEN; -} - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -asmlinkage unsigned long sunos_sigblock(unsigned long blk_mask) -{ - unsigned long old; - - spin_lock_irq(¤t->sighand->siglock); - old = current->blocked.sig[0]; - current->blocked.sig[0] |= (blk_mask & _BLOCKABLE); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return old; -} - -asmlinkage unsigned long sunos_sigsetmask(unsigned long newmask) -{ - unsigned long retval; - - spin_lock_irq(¤t->sighand->siglock); - retval = current->blocked.sig[0]; - current->blocked.sig[0] = (newmask & _BLOCKABLE); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return retval; -} - -/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */ -/* getdents system call, the format of the structure just has a different */ -/* layout (d_off+d_ino instead of d_ino+d_off) */ -struct sunos_dirent { - long d_off; - unsigned long d_ino; - unsigned short d_reclen; - unsigned short d_namlen; - char d_name[1]; -}; - -struct sunos_dirent_callback { - struct sunos_dirent __user *curr; - struct sunos_dirent __user *previous; - int count; - int error; -}; - -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) -#define ROUND_UP(x) (((x)+sizeof(long)-1) & ~(sizeof(long)-1)) - -static int sunos_filldir(void * __buf, const char * name, int namlen, - loff_t offset, u64 ino, unsigned int d_type) -{ - struct sunos_dirent __user *dirent; - struct sunos_dirent_callback * buf = __buf; - unsigned long d_ino; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); - - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; - d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) - return -EOVERFLOW; - dirent = buf->previous; - if (dirent) - put_user(offset, &dirent->d_off); - dirent = buf->curr; - buf->previous = dirent; - put_user(d_ino, &dirent->d_ino); - put_user(namlen, &dirent->d_namlen); - put_user(reclen, &dirent->d_reclen); - copy_to_user(dirent->d_name, name, namlen); - put_user(0, dirent->d_name + namlen); - dirent = (void __user *) dirent + reclen; - buf->curr = dirent; - buf->count -= reclen; - return 0; -} - -asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt) -{ - struct file * file; - struct sunos_dirent __user *lastdirent; - struct sunos_dirent_callback buf; - int error = -EBADF; - - if (fd >= SUNOS_NR_OPEN) - goto out; - - file = fget(fd); - if (!file) - goto out; - - error = -EINVAL; - if (cnt < (sizeof(struct sunos_dirent) + 255)) - goto out_putf; - - buf.curr = (struct sunos_dirent __user *) dirent; - buf.previous = NULL; - buf.count = cnt; - buf.error = 0; - - error = vfs_readdir(file, sunos_filldir, &buf); - if (error < 0) - goto out_putf; - - lastdirent = buf.previous; - error = buf.error; - if (lastdirent) { - put_user(file->f_pos, &lastdirent->d_off); - error = cnt - buf.count; - } - -out_putf: - fput(file); -out: - return error; -} - -/* Old sunos getdirentries, severely broken compatibility stuff here. */ -struct sunos_direntry { - unsigned long d_ino; - unsigned short d_reclen; - unsigned short d_namlen; - char d_name[1]; -}; - -struct sunos_direntry_callback { - struct sunos_direntry __user *curr; - struct sunos_direntry __user *previous; - int count; - int error; -}; - -static int sunos_filldirentry(void * __buf, const char * name, int namlen, - loff_t offset, u64 ino, unsigned int d_type) -{ - struct sunos_direntry __user *dirent; - struct sunos_direntry_callback *buf = __buf; - unsigned long d_ino; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); - - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; - d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) - return -EOVERFLOW; - dirent = buf->previous; - dirent = buf->curr; - buf->previous = dirent; - put_user(d_ino, &dirent->d_ino); - put_user(namlen, &dirent->d_namlen); - put_user(reclen, &dirent->d_reclen); - copy_to_user(dirent->d_name, name, namlen); - put_user(0, dirent->d_name + namlen); - dirent = (void __user *) dirent + reclen; - buf->curr = dirent; - buf->count -= reclen; - return 0; -} - -asmlinkage int sunos_getdirentries(unsigned int fd, void __user *dirent, - int cnt, unsigned int __user *basep) -{ - struct file * file; - struct sunos_direntry __user *lastdirent; - struct sunos_direntry_callback buf; - int error = -EBADF; - - if (fd >= SUNOS_NR_OPEN) - goto out; - - file = fget(fd); - if (!file) - goto out; - - error = -EINVAL; - if (cnt < (sizeof(struct sunos_direntry) + 255)) - goto out_putf; - - buf.curr = (struct sunos_direntry __user *) dirent; - buf.previous = NULL; - buf.count = cnt; - buf.error = 0; - - error = vfs_readdir(file, sunos_filldirentry, &buf); - if (error < 0) - goto out_putf; - - lastdirent = buf.previous; - error = buf.error; - if (lastdirent) { - put_user(file->f_pos, basep); - error = cnt - buf.count; - } - -out_putf: - fput(file); -out: - return error; -} - -struct sunos_utsname { - char sname[9]; - char nname[9]; - char nnext[56]; - char rel[9]; - char ver[9]; - char mach[9]; -}; - -asmlinkage int sunos_uname(struct sunos_utsname __user *name) -{ - int ret; - down_read(&uts_sem); - ret = copy_to_user(&name->sname[0], &utsname()->sysname[0], - sizeof(name->sname) - 1); - if (!ret) { - ret |= __copy_to_user(&name->nname[0], &utsname()->nodename[0], - sizeof(name->nname) - 1); - ret |= __put_user('\0', &name->nname[8]); - ret |= __copy_to_user(&name->rel[0], &utsname()->release[0], - sizeof(name->rel) - 1); - ret |= __copy_to_user(&name->ver[0], &utsname()->version[0], - sizeof(name->ver) - 1); - ret |= __copy_to_user(&name->mach[0], &utsname()->machine[0], - sizeof(name->mach) - 1); - } - up_read(&uts_sem); - return ret ? -EFAULT : 0; -} - -asmlinkage int sunos_nosys(void) -{ - struct pt_regs *regs; - siginfo_t info; - static int cnt; - - lock_kernel(); - regs = current->thread.kregs; - info.si_signo = SIGSYS; - info.si_errno = 0; - info.si_code = __SI_FAULT|0x100; - info.si_addr = (void __user *)regs->pc; - info.si_trapno = regs->u_regs[UREG_G1]; - send_sig_info(SIGSYS, &info, current); - if (cnt++ < 4) { - printk("Process makes ni_syscall number %d, register dump:\n", - (int) regs->u_regs[UREG_G1]); - show_regs(regs); - } - unlock_kernel(); - return -ENOSYS; -} - -/* This is not a real and complete implementation yet, just to keep - * the easy SunOS binaries happy. - */ -asmlinkage int sunos_fpathconf(int fd, int name) -{ - int ret; - - switch(name) { - case _PCONF_LINK: - ret = LINK_MAX; - break; - case _PCONF_CANON: - ret = MAX_CANON; - break; - case _PCONF_INPUT: - ret = MAX_INPUT; - break; - case _PCONF_NAME: - ret = NAME_MAX; - break; - case _PCONF_PATH: - ret = PATH_MAX; - break; - case _PCONF_PIPE: - ret = PIPE_BUF; - break; - case _PCONF_CHRESTRICT: /* XXX Investigate XXX */ - ret = 1; - break; - case _PCONF_NOTRUNC: /* XXX Investigate XXX */ - case _PCONF_VDISABLE: - ret = 0; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -asmlinkage int sunos_pathconf(char __user *path, int name) -{ - int ret; - - ret = sunos_fpathconf(0, name); /* XXX cheese XXX */ - return ret; -} - -/* SunOS mount system call emulation */ - -asmlinkage int sunos_select(int width, fd_set __user *inp, fd_set __user *outp, - fd_set __user *exp, struct timeval __user *tvp) -{ - int ret; - - /* SunOS binaries expect that select won't change the tvp contents */ - ret = sys_select (width, inp, outp, exp, tvp); - if (ret == -EINTR && tvp) { - time_t sec, usec; - - __get_user(sec, &tvp->tv_sec); - __get_user(usec, &tvp->tv_usec); - - if (sec == 0 && usec == 0) - ret = 0; - } - return ret; -} - -asmlinkage void sunos_nop(void) -{ - return; -} - -/* SunOS mount/umount. */ -#define SMNT_RDONLY 1 -#define SMNT_NOSUID 2 -#define SMNT_NEWTYPE 4 -#define SMNT_GRPID 8 -#define SMNT_REMOUNT 16 -#define SMNT_NOSUB 32 -#define SMNT_MULTI 64 -#define SMNT_SYS5 128 - -struct sunos_fh_t { - char fh_data [NFS_FHSIZE]; -}; - -struct sunos_nfs_mount_args { - struct sockaddr_in __user *addr; /* file server address */ - struct nfs_fh __user *fh; /* File handle to be mounted */ - int flags; /* flags */ - int wsize; /* write size in bytes */ - int rsize; /* read size in bytes */ - int timeo; /* initial timeout in .1 secs */ - int retrans; /* times to retry send */ - char __user *hostname; /* server's hostname */ - int acregmin; /* attr cache file min secs */ - int acregmax; /* attr cache file max secs */ - int acdirmin; /* attr cache dir min secs */ - int acdirmax; /* attr cache dir max secs */ - char __user *netname; /* server's netname */ -}; - - -/* Bind the socket on a local reserved port and connect it to the - * remote server. This on Linux/i386 is done by the mount program, - * not by the kernel. - */ -static int -sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) -{ - struct sockaddr_in local; - struct sockaddr_in server; - int try_port; - struct socket *socket; - struct inode *inode; - struct file *file; - int ret, result = 0; - - file = fget(fd); - if (!file) - goto out; - - inode = file->f_path.dentry->d_inode; - - socket = SOCKET_I(inode); - local.sin_family = AF_INET; - local.sin_addr.s_addr = htonl(INADDR_ANY); - - /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */ - try_port = 1024; - do { - local.sin_port = htons (--try_port); - ret = socket->ops->bind(socket, (struct sockaddr*)&local, - sizeof(local)); - } while (ret && try_port > (1024 / 2)); - - if (ret) - goto out_putf; - - server.sin_family = AF_INET; - server.sin_addr = addr->sin_addr; - server.sin_port = NFS_PORT; - - /* Call sys_connect */ - ret = socket->ops->connect (socket, (struct sockaddr *) &server, - sizeof (server), file->f_flags); - if (ret >= 0) - result = 1; - -out_putf: - fput(file); -out: - return result; -} - -static int get_default (int value, int def_value) -{ - if (value) - return value; - else - return def_value; -} - -static int sunos_nfs_mount(char *dir_name, int linux_flags, void __user *data) -{ - int server_fd, err; - char *the_name, *mount_page; - struct nfs_mount_data linux_nfs_mount; - struct sunos_nfs_mount_args sunos_mount; - - /* Ok, here comes the fun part: Linux's nfs mount needs a - * socket connection to the server, but SunOS mount does not - * require this, so we use the information on the destination - * address to create a socket and bind it to a reserved - * port on this system - */ - if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount))) - return -EFAULT; - - server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (server_fd < 0) - return -ENXIO; - - if (copy_from_user(&linux_nfs_mount.addr,sunos_mount.addr, - sizeof(*sunos_mount.addr)) || - copy_from_user(&linux_nfs_mount.root,sunos_mount.fh, - sizeof(*sunos_mount.fh))) { - sys_close (server_fd); - return -EFAULT; - } - - if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ - sys_close (server_fd); - return -ENXIO; - } - - /* Now, bind it to a locally reserved port */ - linux_nfs_mount.version = NFS_MOUNT_VERSION; - linux_nfs_mount.flags = sunos_mount.flags; - linux_nfs_mount.fd = server_fd; - - linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); - linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); - linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); - linux_nfs_mount.retrans = sunos_mount.retrans; - - linux_nfs_mount.acregmin = sunos_mount.acregmin; - linux_nfs_mount.acregmax = sunos_mount.acregmax; - linux_nfs_mount.acdirmin = sunos_mount.acdirmin; - linux_nfs_mount.acdirmax = sunos_mount.acdirmax; - - the_name = getname(sunos_mount.hostname); - if (IS_ERR(the_name)) - return PTR_ERR(the_name); - - strlcpy(linux_nfs_mount.hostname, the_name, - sizeof(linux_nfs_mount.hostname)); - putname (the_name); - - mount_page = (char *) get_zeroed_page(GFP_KERNEL); - if (!mount_page) - return -ENOMEM; - - memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount)); - - err = do_mount("", dir_name, "nfs", linux_flags, mount_page); - - free_page((unsigned long) mount_page); - return err; -} - -asmlinkage int -sunos_mount(char __user *type, char __user *dir, int flags, void __user *data) -{ - int linux_flags = 0; - int ret = -EINVAL; - char *dev_fname = NULL; - char *dir_page, *type_page; - - if (!capable (CAP_SYS_ADMIN)) - return -EPERM; - - lock_kernel(); - /* We don't handle the integer fs type */ - if ((flags & SMNT_NEWTYPE) == 0) - goto out; - - /* Do not allow for those flags we don't support */ - if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5)) - goto out; - - if (flags & SMNT_REMOUNT) - linux_flags |= MS_REMOUNT; - if (flags & SMNT_RDONLY) - linux_flags |= MS_RDONLY; - if (flags & SMNT_NOSUID) - linux_flags |= MS_NOSUID; - - dir_page = getname(dir); - ret = PTR_ERR(dir_page); - if (IS_ERR(dir_page)) - goto out; - - type_page = getname(type); - ret = PTR_ERR(type_page); - if (IS_ERR(type_page)) - goto out1; - - if (strcmp(type_page, "ext2") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "iso9660") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "minix") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "nfs") == 0) { - ret = sunos_nfs_mount (dir_page, flags, data); - goto out2; - } else if (strcmp(type_page, "ufs") == 0) { - printk("Warning: UFS filesystem mounts unsupported.\n"); - ret = -ENODEV; - goto out2; - } else if (strcmp(type_page, "proc")) { - ret = -ENODEV; - goto out2; - } - ret = PTR_ERR(dev_fname); - if (IS_ERR(dev_fname)) - goto out2; - ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL); - if (dev_fname) - putname(dev_fname); -out2: - putname(type_page); -out1: - putname(dir_page); -out: - unlock_kernel(); - return ret; -} - - -asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid) -{ - int ret; - - /* So stupid... */ - if ((!pid || pid == current->pid) && - !pgid) { - sys_setsid(); - ret = 0; - } else { - ret = sys_setpgid(pid, pgid); - } - return ret; -} - -/* So stupid... */ -asmlinkage int sunos_wait4(pid_t pid, unsigned int __user *stat_addr, - int options, struct rusage __user*ru) -{ - int ret; - - ret = sys_wait4((pid ? pid : -1), stat_addr, options, ru); - return ret; -} - -asmlinkage int sunos_killpg(int pgrp, int sig) -{ - int ret; - - rcu_read_lock(); - ret = -EINVAL; - if (pgrp > 0) - ret = kill_pgrp(find_vpid(pgrp), sig, 0); - rcu_read_unlock(); - - return ret; -} - -asmlinkage int sunos_audit(void) -{ - lock_kernel(); - printk ("sys_audit\n"); - unlock_kernel(); - return -1; -} - -asmlinkage unsigned long sunos_gethostid(void) -{ - unsigned long ret; - - lock_kernel(); - ret = ((unsigned long)idprom->id_machtype << 24) | - (unsigned long)idprom->id_sernum; - unlock_kernel(); - return ret; -} - -/* sysconf options, for SunOS compatibility */ -#define _SC_ARG_MAX 1 -#define _SC_CHILD_MAX 2 -#define _SC_CLK_TCK 3 -#define _SC_NGROUPS_MAX 4 -#define _SC_OPEN_MAX 5 -#define _SC_JOB_CONTROL 6 -#define _SC_SAVED_IDS 7 -#define _SC_VERSION 8 - -asmlinkage long sunos_sysconf (int name) -{ - long ret; - - switch (name){ - case _SC_ARG_MAX: - ret = ARG_MAX; - break; - case _SC_CHILD_MAX: - ret = current->signal->rlim[RLIMIT_NPROC].rlim_cur; - break; - case _SC_CLK_TCK: - ret = HZ; - break; - case _SC_NGROUPS_MAX: - ret = NGROUPS_MAX; - break; - case _SC_OPEN_MAX: - ret = current->signal->rlim[RLIMIT_NOFILE].rlim_cur; - break; - case _SC_JOB_CONTROL: - ret = 1; /* yes, we do support job control */ - break; - case _SC_SAVED_IDS: - ret = 1; /* yes, we do support saved uids */ - break; - case _SC_VERSION: - /* mhm, POSIX_VERSION is in /usr/include/unistd.h - * should it go on /usr/include/linux? - */ - ret = 199009L; - break; - default: - ret = -1; - break; - }; - return ret; -} - -asmlinkage int sunos_semsys(int op, unsigned long arg1, unsigned long arg2, - unsigned long arg3, void *ptr) -{ - union semun arg4; - int ret; - - switch (op) { - case 0: - /* Most arguments match on a 1:1 basis but cmd doesn't */ - switch(arg3) { - case 4: - arg3=GETPID; break; - case 5: - arg3=GETVAL; break; - case 6: - arg3=GETALL; break; - case 3: - arg3=GETNCNT; break; - case 7: - arg3=GETZCNT; break; - case 8: - arg3=SETVAL; break; - case 9: - arg3=SETALL; break; - } - /* sys_semctl(): */ - /* value to modify semaphore to */ - arg4.__pad = (void __user *) ptr; - ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4 ); - break; - case 1: - /* sys_semget(): */ - ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3); - break; - case 2: - /* sys_semop(): */ - ret = sys_semop((int)arg1, (struct sembuf __user *)arg2, (unsigned)arg3); - break; - default: - ret = -EINVAL; - break; - }; - return ret; -} - -asmlinkage int sunos_msgsys(int op, unsigned long arg1, unsigned long arg2, - unsigned long arg3, unsigned long arg4) -{ - struct sparc_stackf *sp; - unsigned long arg5; - int rval; - - switch(op) { - case 0: - rval = sys_msgget((key_t)arg1, (int)arg2); - break; - case 1: - rval = sys_msgctl((int)arg1, (int)arg2, - (struct msqid_ds __user *)arg3); - break; - case 2: - lock_kernel(); - sp = (struct sparc_stackf *)current->thread.kregs->u_regs[UREG_FP]; - arg5 = sp->xxargs[0]; - unlock_kernel(); - rval = sys_msgrcv((int)arg1, (struct msgbuf __user *)arg2, - (size_t)arg3, (long)arg4, (int)arg5); - break; - case 3: - rval = sys_msgsnd((int)arg1, (struct msgbuf __user *)arg2, - (size_t)arg3, (int)arg4); - break; - default: - rval = -EINVAL; - break; - } - return rval; -} - -asmlinkage int sunos_shmsys(int op, unsigned long arg1, unsigned long arg2, - unsigned long arg3) -{ - unsigned long raddr; - int rval; - - switch(op) { - case 0: - /* do_shmat(): attach a shared memory area */ - rval = do_shmat((int)arg1,(char __user *)arg2,(int)arg3,&raddr); - if (!rval) - rval = (int) raddr; - break; - case 1: - /* sys_shmctl(): modify shared memory area attr. */ - rval = sys_shmctl((int)arg1,(int)arg2,(struct shmid_ds __user *)arg3); - break; - case 2: - /* sys_shmdt(): detach a shared memory area */ - rval = sys_shmdt((char __user *)arg1); - break; - case 3: - /* sys_shmget(): get a shared memory area */ - rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3); - break; - default: - rval = -EINVAL; - break; - }; - return rval; -} - -#define SUNOS_EWOULDBLOCK 35 - -/* see the sunos man page read(2v) for an explanation - of this garbage. We use O_NDELAY to mark - file descriptors that have been set non-blocking - using 4.2BSD style calls. (tridge) */ - -static inline int check_nonblock(int ret, int fd) -{ - if (ret == -EAGAIN) { - struct file * file = fget(fd); - if (file) { - if (file->f_flags & O_NDELAY) - ret = -SUNOS_EWOULDBLOCK; - fput(file); - } - } - return ret; -} - -asmlinkage int sunos_read(unsigned int fd, char __user *buf, int count) -{ - int ret; - - ret = check_nonblock(sys_read(fd,buf,count),fd); - return ret; -} - -asmlinkage int sunos_readv(unsigned long fd, const struct iovec __user *vector, - long count) -{ - int ret; - - ret = check_nonblock(sys_readv(fd,vector,count),fd); - return ret; -} - -asmlinkage int sunos_write(unsigned int fd, char __user *buf, int count) -{ - int ret; - - ret = check_nonblock(sys_write(fd,buf,count),fd); - return ret; -} - -asmlinkage int sunos_writev(unsigned long fd, - const struct iovec __user *vector, long count) -{ - int ret; - - ret = check_nonblock(sys_writev(fd,vector,count),fd); - return ret; -} - -asmlinkage int sunos_recv(int fd, void __user *ubuf, int size, unsigned flags) -{ - int ret; - - ret = check_nonblock(sys_recv(fd,ubuf,size,flags),fd); - return ret; -} - -asmlinkage int sunos_send(int fd, void __user *buff, int len, unsigned flags) -{ - int ret; - - ret = check_nonblock(sys_send(fd,buff,len,flags),fd); - return ret; -} - -asmlinkage int sunos_accept(int fd, struct sockaddr __user *sa, - int __user *addrlen) -{ - int ret; - - while (1) { - ret = check_nonblock(sys_accept(fd,sa,addrlen),fd); - if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) - break; - } - - return ret; -} - -#define SUNOS_SV_INTERRUPT 2 - -asmlinkage int -sunos_sigaction(int sig, const struct old_sigaction __user *act, - struct old_sigaction __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - old_sigset_t mask; - - if (!access_ok(VERIFY_READ, act, sizeof(*act)) || - __get_user(new_ka.sa.sa_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_flags, &act->sa_flags)) - return -EFAULT; - __get_user(mask, &act->sa_mask); - new_ka.sa.sa_restorer = NULL; - new_ka.ka_restorer = NULL; - siginitset(&new_ka.sa.sa_mask, mask); - new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT; - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - /* In the clone() case we could copy half consistent - * state to the user, however this could sleep and - * deadlock us if we held the signal lock on SMP. So for - * now I take the easy way out and do no locking. - * But then again we don't support SunOS lwp's anyways ;-) - */ - old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT; - if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || - __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || - __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) - return -EFAULT; - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - - -asmlinkage int sunos_setsockopt(int fd, int level, int optname, - char __user *optval, int optlen) -{ - int tr_opt = optname; - int ret; - - if (level == SOL_IP) { - /* Multicast socketopts (ttl, membership) */ - if (tr_opt >=2 && tr_opt <= 6) - tr_opt += 30; - } - ret = sys_setsockopt(fd, level, tr_opt, optval, optlen); - return ret; -} - -asmlinkage int sunos_getsockopt(int fd, int level, int optname, - char __user *optval, int __user *optlen) -{ - int tr_opt = optname; - int ret; - - if (level == SOL_IP) { - /* Multicast socketopts (ttl, membership) */ - if (tr_opt >=2 && tr_opt <= 6) - tr_opt += 30; - } - ret = sys_getsockopt(fd, level, tr_opt, optval, optlen); - return ret; -} diff --git a/arch/sparc/kernel/systbls.S b/arch/sparc/kernel/systbls.S index 9064485dc40b..5a7c4c8345c3 100644 --- a/arch/sparc/kernel/systbls.S +++ b/arch/sparc/kernel/systbls.S @@ -81,124 +81,3 @@ sys_call_table: /*305*/ .long sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait /*310*/ .long sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate /*315*/ .long sys_timerfd_settime, sys_timerfd_gettime - -#ifdef CONFIG_SUNOS_EMUL - /* Now the SunOS syscall table. */ - - .align 4 - .globl sunos_sys_table -sunos_sys_table: -/*0*/ .long sunos_indir, sys_exit, sys_fork - .long sunos_read, sunos_write, sys_open - .long sys_close, sunos_wait4, sys_creat - .long sys_link, sys_unlink, sunos_execv - .long sys_chdir, sunos_nosys, sys_mknod - .long sys_chmod, sys_lchown16, sunos_brk - .long sunos_nosys, sys_lseek, sunos_getpid - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_getuid, sunos_nosys, sys_ptrace - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sys_access, sunos_nosys, sunos_nosys - .long sys_sync, sys_kill, sys_newstat - .long sunos_nosys, sys_newlstat, sys_dup - .long sys_pipe, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_getgid - .long sunos_nosys, sunos_nosys -/*50*/ .long sunos_nosys, sys_acct, sunos_nosys - .long sunos_mctl, sunos_ioctl, sys_reboot - .long sunos_nosys, sys_symlink, sys_readlink - .long sys_execve, sys_umask, sys_chroot - .long sys_newfstat, sunos_nosys, sys_getpagesize - .long sys_msync, sys_vfork, sunos_nosys - .long sunos_nosys, sunos_sbrk, sunos_sstk - .long sunos_mmap, sunos_vadvise, sys_munmap - .long sys_mprotect, sys_madvise, sys_vhangup - .long sunos_nosys, sys_mincore, sys_getgroups16 - .long sys_setgroups16, sys_getpgrp, sunos_setpgrp - .long sys_setitimer, sunos_nosys, sys_swapon - .long sys_getitimer, sys_gethostname, sys_sethostname - .long sunos_getdtablesize, sys_dup2, sunos_nop - .long sys_fcntl, sunos_select, sunos_nop - .long sys_fsync, sys_setpriority, sys_socket - .long sys_connect, sunos_accept -/*100*/ .long sys_getpriority, sunos_send, sunos_recv - .long sunos_nosys, sys_bind, sunos_setsockopt - .long sys_listen, sunos_nosys, sunos_sigaction - .long sunos_sigblock, sunos_sigsetmask, sys_sigpause - .long sys_sigstack, sys_recvmsg, sys_sendmsg - .long sunos_nosys, sys_gettimeofday, sys_getrusage - .long sunos_getsockopt, sunos_nosys, sunos_readv - .long sunos_writev, sys_settimeofday, sys_fchown16 - .long sys_fchmod, sys_recvfrom, sys_setreuid16 - .long sys_setregid16, sys_rename, sys_truncate - .long sys_ftruncate, sys_flock, sunos_nosys - .long sys_sendto, sys_shutdown, sys_socketpair - .long sys_mkdir, sys_rmdir, sys_utimes - .long sys_sigreturn, sunos_nosys, sys_getpeername - .long sunos_gethostid, sunos_nosys, sys_getrlimit - .long sys_setrlimit, sunos_killpg, sunos_nosys - .long sunos_nosys, sunos_nosys -/*150*/ .long sys_getsockname, sunos_nosys, sunos_nosys - .long sys_poll, sunos_nosys, sunos_nosys - .long sunos_getdirentries, sys_statfs, sys_fstatfs - .long sys_oldumount, sunos_nosys, sunos_nosys - .long sys_getdomainname, sys_setdomainname - .long sunos_nosys, sys_quotactl, sunos_nosys - .long sunos_mount, sys_ustat, sunos_semsys - .long sunos_msgsys, sunos_shmsys, sunos_audit - .long sunos_nosys, sunos_getdents, sys_setsid - .long sys_fchdir, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sys_sigpending, sunos_nosys - .long sys_setpgid, sunos_pathconf, sunos_fpathconf - .long sunos_sysconf, sunos_uname, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys -/*200*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys -/*250*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys -/*260*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys -/*270*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys -/*280*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys -/*290*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys -/*300*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys -/*310*/ .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys, sunos_nosys, sunos_nosys - .long sunos_nosys - -#endif diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 463d1be32c98..b782d874759c 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -87,9 +87,6 @@ config GENERIC_HARDIRQS_NO__DO_IRQ bool def_bool y -config ARCH_SUPPORTS_AOUT - def_bool y - choice prompt "Kernel page size" default SPARC64_PAGE_SIZE_8KB @@ -147,11 +144,6 @@ config HOTPLUG_CPU source "init/Kconfig" -config SYSVIPC_COMPAT - bool - depends on COMPAT && SYSVIPC - default y - config GENERIC_HARDIRQS bool default y @@ -379,6 +371,10 @@ config SUN_OPENPROMFS To compile the /proc/openprom support as a module, choose M here: the module will be called openpromfs. If unsure, choose M. +menu "Executable file formats" + +source "fs/Kconfig.binfmt" + config SPARC32_COMPAT bool "Kernel support for Linux/Sparc 32bit binary compatibility" help @@ -391,37 +387,10 @@ config COMPAT default y select COMPAT_BINFMT_ELF -config BINFMT_AOUT32 - bool "Kernel support for 32-bit (ie. SunOS) a.out binaries" - depends on SPARC32_COMPAT && ARCH_SUPPORTS_AOUT - help - This allows you to run 32-bit a.out format binaries on your Ultra. - If you want to run SunOS binaries (see SunOS binary emulation below) - or other a.out binaries, say Y. If unsure, say N. - -menu "Executable file formats" - -source "fs/Kconfig.binfmt" - -config SUNOS_EMUL - bool "SunOS binary emulation" - depends on BINFMT_AOUT32 - help - This allows you to run most SunOS binaries. If you want to do this, - say Y here and place appropriate files in /usr/gnemul/sunos. See - for more information. If you - want to run SunOS binaries on an Ultra you must also say Y to - "Kernel support for 32-bit a.out binaries" above. - -config SOLARIS_EMUL - tristate "Solaris binary emulation (EXPERIMENTAL)" - depends on SPARC32_COMPAT && NET && EXPERIMENTAL - help - This is experimental code which will enable you to run (many) - Solaris binaries on your SPARC Linux machine. - - To compile this code as a module, choose M here: the - module will be called solaris. +config SYSVIPC_COMPAT + bool + depends on COMPAT && SYSVIPC + default y endmenu diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile index f0c22f826982..9cb75c852b45 100644 --- a/arch/sparc64/Makefile +++ b/arch/sparc64/Makefile @@ -27,7 +27,6 @@ endif head-y := arch/sparc64/kernel/head.o arch/sparc64/kernel/init_task.o core-y += arch/sparc64/kernel/ arch/sparc64/mm/ -core-$(CONFIG_SOLARIS_EMUL) += arch/sparc64/solaris/ core-y += arch/sparc64/math-emu/ libs-y += arch/sparc64/prom/ arch/sparc64/lib/ drivers-$(CONFIG_OPROFILE) += arch/sparc64/oprofile/ diff --git a/arch/sparc64/defconfig b/arch/sparc64/defconfig index 9d4bd2229493..e1835868ad36 100644 --- a/arch/sparc64/defconfig +++ b/arch/sparc64/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.25-rc3 -# Wed Mar 26 04:33:35 2008 +# Linux kernel version: 2.6.25 +# Sun Apr 20 01:33:21 2008 # CONFIG_SPARC=y CONFIG_SPARC64=y @@ -22,7 +22,6 @@ CONFIG_HAVE_SETUP_PER_CPU_AREA=y CONFIG_ARCH_NO_VIRT_TO_BUS=y CONFIG_OF=y CONFIG_GENERIC_HARDIRQS_NO__DO_IRQ=y -CONFIG_ARCH_SUPPORTS_AOUT=y CONFIG_SPARC64_PAGE_SIZE_8KB=y # CONFIG_SPARC64_PAGE_SIZE_64KB is not set # CONFIG_SPARC64_PAGE_SIZE_512KB is not set @@ -61,6 +60,7 @@ CONFIG_RT_GROUP_SCHED=y CONFIG_USER_SCHED=y # CONFIG_CGROUP_SCHED is not set CONFIG_SYSFS_DEPRECATED=y +CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_RELAY=y CONFIG_NAMESPACES=y # CONFIG_UTS_NS is not set @@ -100,7 +100,9 @@ CONFIG_PROFILING=y CONFIG_OPROFILE=m CONFIG_HAVE_OPROFILE=y CONFIG_KPROBES=y +CONFIG_KRETPROBES=y CONFIG_HAVE_KPROBES=y +CONFIG_HAVE_KRETPROBES=y CONFIG_PROC_PAGE_MONITOR=y CONFIG_SLABINFO=y CONFIG_RT_MUTEXES=y @@ -131,8 +133,6 @@ CONFIG_DEFAULT_AS=y # CONFIG_DEFAULT_NOOP is not set CONFIG_DEFAULT_IOSCHED="anticipatory" CONFIG_CLASSIC_RCU=y -# CONFIG_PREEMPT_RCU is not set -CONFIG_SYSVIPC_COMPAT=y CONFIG_GENERIC_HARDIRQS=y # @@ -182,9 +182,6 @@ CONFIG_PCI_MSI=y # CONFIG_PCI_LEGACY is not set # CONFIG_PCI_DEBUG is not set CONFIG_SUN_OPENPROMFS=m -CONFIG_SPARC32_COMPAT=y -CONFIG_COMPAT=y -# CONFIG_BINFMT_AOUT32 is not set # # Executable file formats @@ -192,13 +189,14 @@ CONFIG_COMPAT=y CONFIG_BINFMT_ELF=y CONFIG_COMPAT_BINFMT_ELF=y CONFIG_BINFMT_MISC=m -CONFIG_SOLARIS_EMUL=y +CONFIG_SPARC32_COMPAT=y +CONFIG_COMPAT=y +CONFIG_SYSVIPC_COMPAT=y CONFIG_SCHED_SMT=y CONFIG_SCHED_MC=y # CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y # CONFIG_PREEMPT is not set -# CONFIG_RCU_TRACE is not set # CONFIG_CMDLINE_BOOL is not set # @@ -263,8 +261,10 @@ CONFIG_INET6_XFRM_MODE_TUNNEL=m CONFIG_INET6_XFRM_MODE_BEET=m # CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set CONFIG_IPV6_SIT=m +CONFIG_IPV6_NDISC_NODETYPE=y CONFIG_IPV6_TUNNEL=m # CONFIG_IPV6_MULTIPLE_TABLES is not set +# CONFIG_IPV6_MROUTE is not set # CONFIG_NETWORK_SECMARK is not set # CONFIG_NETFILTER is not set CONFIG_IP_DCCP=m @@ -368,7 +368,7 @@ CONFIG_IDE=y CONFIG_BLK_DEV_IDE=y # -# Please see Documentation/ide.txt for help/info on IDE drives +# Please see Documentation/ide/ide.txt for help/info on IDE drives # # CONFIG_BLK_DEV_IDE_SATA is not set CONFIG_BLK_DEV_IDEDISK=y @@ -384,7 +384,6 @@ CONFIG_IDE_PROC_FS=y # # IDE chipset support/bugfixes # -CONFIG_IDE_GENERIC=y # CONFIG_BLK_DEV_PLATFORM is not set CONFIG_BLK_DEV_IDEDMA_SFF=y @@ -422,7 +421,7 @@ CONFIG_BLK_DEV_ALI15X3=y # CONFIG_BLK_DEV_VIA82CXXX is not set # CONFIG_BLK_DEV_TC86C001 is not set CONFIG_BLK_DEV_IDEDMA=y -CONFIG_IDE_ARCH_OBSOLETE_INIT=y +# CONFIG_BLK_DEV_HD_ONLY is not set # CONFIG_BLK_DEV_HD is not set # @@ -588,7 +587,6 @@ CONFIG_E1000_NAPI=y # CONFIG_SIS190 is not set # CONFIG_SKGE is not set # CONFIG_SKY2 is not set -# CONFIG_SK98LIN is not set # CONFIG_VIA_VELOCITY is not set CONFIG_TIGON3=m CONFIG_BNX2=m @@ -613,6 +611,7 @@ CONFIG_NIU=m # # CONFIG_WLAN_PRE80211 is not set # CONFIG_WLAN_80211 is not set +# CONFIG_IWLWIFI_LEDS is not set # # USB Network Adapters @@ -1472,7 +1471,7 @@ CONFIG_CRYPTO_MICHAEL_MIC=m CONFIG_CRYPTO_CRC32C=m CONFIG_CRYPTO_CAMELLIA=m CONFIG_CRYPTO_TEST=m -CONFIG_CRYPTO_AUTHENC=m +CONFIG_CRYPTO_AUTHENC=y # CONFIG_CRYPTO_LZO is not set CONFIG_CRYPTO_HW=y # CONFIG_CRYPTO_DEV_HIFN_795X is not set diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 459462e80a12..63c6ae0dd273 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_PCI) += ebus.o isa.o pci_common.o \ obj-$(CONFIG_PCI_MSI) += pci_msi.o obj-$(CONFIG_SMP) += smp.o trampoline.o hvtramp.o obj-$(CONFIG_SPARC32_COMPAT) += sys32.o sys_sparc32.o signal32.o -obj-$(CONFIG_BINFMT_AOUT32) += binfmt_aout32.o obj-$(CONFIG_MODULES) += module.o obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o @@ -30,11 +29,3 @@ obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o obj-$(CONFIG_AUDIT) += audit.o obj-$(CONFIG_AUDIT)$(CONFIG_SPARC32_COMPAT) += compat_audit.o obj-y += $(obj-yy) - -ifdef CONFIG_SUNOS_EMUL - obj-y += sys_sunos32.o sunos_ioctl32.o -else - ifdef CONFIG_SOLARIS_EMUL - obj-y += sys_sunos32.o sunos_ioctl32.o - endif -endif diff --git a/arch/sparc64/kernel/binfmt_aout32.c b/arch/sparc64/kernel/binfmt_aout32.c deleted file mode 100644 index 9877f2d7672d..000000000000 --- a/arch/sparc64/kernel/binfmt_aout32.c +++ /dev/null @@ -1,419 +0,0 @@ -/* - * linux/fs/binfmt_aout.c - * - * Copyright (C) 1991, 1992, 1996 Linus Torvalds - * - * Hacked a bit by DaveM to make it work with 32-bit SunOS - * binaries on the sparc64 port. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -static int load_aout32_binary(struct linux_binprm *, struct pt_regs * regs); -static int load_aout32_library(struct file*); -static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit); - -static struct linux_binfmt aout32_format = { - .module = THIS_MODULE, - .load_binary = load_aout32_binary, - .load_shlib = load_aout32_library, - .core_dump = aout32_core_dump, - .min_coredump = PAGE_SIZE, -}; - -static void set_brk(unsigned long start, unsigned long end) -{ - start = PAGE_ALIGN(start); - end = PAGE_ALIGN(end); - if (end <= start) - return; - down_write(¤t->mm->mmap_sem); - do_brk(start, end - start); - up_write(¤t->mm->mmap_sem); -} - -/* - * These are the only things you should do on a core-file: use only these - * macros to write out all the necessary info. - */ - -static int dump_write(struct file *file, const void *addr, int nr) -{ - return file->f_op->write(file, addr, nr, &file->f_pos) == nr; -} - -#define DUMP_WRITE(addr, nr) \ - if (!dump_write(file, (void *)(addr), (nr))) \ - goto end_coredump; - -#define DUMP_SEEK(offset) \ -if (file->f_op->llseek) { \ - if (file->f_op->llseek(file,(offset),0) != (offset)) \ - goto end_coredump; \ -} else file->f_pos = (offset) - -/* - * Routine writes a core dump image in the current directory. - * Currently only a stub-function. - * - * Note that setuid/setgid files won't make a core-dump if the uid/gid - * changed due to the set[u|g]id. It's enforced by the "current->mm->dumpable" - * field, which also makes sure the core-dumps won't be recursive if the - * dumping of the process results in another error.. - */ - -static int aout32_core_dump(long signr, struct pt_regs *regs, struct file *file, unsigned long limit) -{ - mm_segment_t fs; - int has_dumped = 0; - unsigned long dump_start, dump_size; - struct user dump; -# define START_DATA(u) (u.u_tsize) -# define START_STACK(u) ((regs->u_regs[UREG_FP]) & ~(PAGE_SIZE - 1)) - - fs = get_fs(); - set_fs(KERNEL_DS); - has_dumped = 1; - current->flags |= PF_DUMPCORE; - strncpy(dump.u_comm, current->comm, sizeof(dump.u_comm)); - dump.signal = signr; - aout_dump_thread(regs, &dump); - -/* If the size of the dump file exceeds the rlimit, then see what would happen - if we wrote the stack, but not the data area. */ - if (dump.u_dsize + dump.u_ssize > limit) - dump.u_dsize = 0; - -/* Make sure we have enough room to write the stack and data areas. */ - if (dump.u_ssize > limit) - dump.u_ssize = 0; - -/* make sure we actually have a data and stack area to dump */ - set_fs(USER_DS); - if (!access_ok(VERIFY_READ, (void __user *) START_DATA(dump), dump.u_dsize)) - dump.u_dsize = 0; - if (!access_ok(VERIFY_READ, (void __user *) START_STACK(dump), dump.u_ssize)) - dump.u_ssize = 0; - - set_fs(KERNEL_DS); -/* struct user */ - DUMP_WRITE(&dump,sizeof(dump)); -/* now we start writing out the user space info */ - set_fs(USER_DS); -/* Dump the data area */ - if (dump.u_dsize != 0) { - dump_start = START_DATA(dump); - dump_size = dump.u_dsize; - DUMP_WRITE(dump_start,dump_size); - } -/* Now prepare to dump the stack area */ - if (dump.u_ssize != 0) { - dump_start = START_STACK(dump); - dump_size = dump.u_ssize; - DUMP_WRITE(dump_start,dump_size); - } -/* Finally dump the task struct. Not be used by gdb, but could be useful */ - set_fs(KERNEL_DS); - DUMP_WRITE(current,sizeof(*current)); -end_coredump: - set_fs(fs); - return has_dumped; -} - -/* - * create_aout32_tables() parses the env- and arg-strings in new user - * memory and creates the pointer tables from them, and puts their - * addresses on the "stack", returning the new stack pointer value. - */ - -static u32 __user *create_aout32_tables(char __user *p, struct linux_binprm *bprm) -{ - u32 __user *argv; - u32 __user *envp; - u32 __user *sp; - int argc = bprm->argc; - int envc = bprm->envc; - - sp = (u32 __user *)((-(unsigned long)sizeof(char *))&(unsigned long)p); - - /* This imposes the proper stack alignment for a new process. */ - sp = (u32 __user *) (((unsigned long) sp) & ~7); - if ((envc+argc+3)&1) - --sp; - - sp -= envc+1; - envp = sp; - sp -= argc+1; - argv = sp; - put_user(argc,--sp); - current->mm->arg_start = (unsigned long) p; - while (argc-->0) { - char c; - put_user(((u32)(unsigned long)(p)),argv++); - do { - get_user(c,p++); - } while (c); - } - put_user(0,argv); - current->mm->arg_end = current->mm->env_start = (unsigned long) p; - while (envc-->0) { - char c; - put_user(((u32)(unsigned long)(p)),envp++); - do { - get_user(c,p++); - } while (c); - } - put_user(0,envp); - current->mm->env_end = (unsigned long) p; - return sp; -} - -/* - * These are the functions used to load a.out style executables and shared - * libraries. There is no binary dependent code anywhere else. - */ - -static int load_aout32_binary(struct linux_binprm * bprm, struct pt_regs * regs) -{ - struct exec ex; - unsigned long error; - unsigned long fd_offset; - unsigned long rlim; - unsigned long orig_thr_flags; - int retval; - - ex = *((struct exec *) bprm->buf); /* exec-header */ - if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != OMAGIC && - N_MAGIC(ex) != QMAGIC && N_MAGIC(ex) != NMAGIC) || - N_TRSIZE(ex) || N_DRSIZE(ex) || - bprm->file->f_path.dentry->d_inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { - return -ENOEXEC; - } - - fd_offset = N_TXTOFF(ex); - - /* Check initial limits. This avoids letting people circumvent - * size limits imposed on them by creating programs with large - * arrays in the data or bss. - */ - rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; - if (rlim >= RLIM_INFINITY) - rlim = ~0; - if (ex.a_data + ex.a_bss > rlim) - return -ENOMEM; - - /* Flush all traces of the currently running executable */ - retval = flush_old_exec(bprm); - if (retval) - return retval; - - /* OK, This is the point of no return */ - set_personality(PER_SUNOS); - - current->mm->end_code = ex.a_text + - (current->mm->start_code = N_TXTADDR(ex)); - current->mm->end_data = ex.a_data + - (current->mm->start_data = N_DATADDR(ex)); - current->mm->brk = ex.a_bss + - (current->mm->start_brk = N_BSSADDR(ex)); - current->mm->free_area_cache = current->mm->mmap_base; - current->mm->cached_hole_size = 0; - - current->mm->mmap = NULL; - compute_creds(bprm); - current->flags &= ~PF_FORKNOEXEC; - if (N_MAGIC(ex) == NMAGIC) { - loff_t pos = fd_offset; - /* Fuck me plenty... */ - down_write(¤t->mm->mmap_sem); - error = do_brk(N_TXTADDR(ex), ex.a_text); - up_write(¤t->mm->mmap_sem); - bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), - ex.a_text, &pos); - down_write(¤t->mm->mmap_sem); - error = do_brk(N_DATADDR(ex), ex.a_data); - up_write(¤t->mm->mmap_sem); - bprm->file->f_op->read(bprm->file, (char __user *)N_DATADDR(ex), - ex.a_data, &pos); - goto beyond_if; - } - - if (N_MAGIC(ex) == OMAGIC) { - loff_t pos = fd_offset; - down_write(¤t->mm->mmap_sem); - do_brk(N_TXTADDR(ex) & PAGE_MASK, - ex.a_text+ex.a_data + PAGE_SIZE - 1); - up_write(¤t->mm->mmap_sem); - bprm->file->f_op->read(bprm->file, (char __user *)N_TXTADDR(ex), - ex.a_text+ex.a_data, &pos); - } else { - static unsigned long error_time; - if ((ex.a_text & 0xfff || ex.a_data & 0xfff) && - (N_MAGIC(ex) != NMAGIC) && (jiffies-error_time) > 5*HZ) - { - printk(KERN_NOTICE "executable not page aligned\n"); - error_time = jiffies; - } - - if (!bprm->file->f_op->mmap) { - loff_t pos = fd_offset; - down_write(¤t->mm->mmap_sem); - do_brk(0, ex.a_text+ex.a_data); - up_write(¤t->mm->mmap_sem); - bprm->file->f_op->read(bprm->file, - (char __user *)N_TXTADDR(ex), - ex.a_text+ex.a_data, &pos); - goto beyond_if; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text, - PROT_READ | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, - fd_offset); - up_write(¤t->mm->mmap_sem); - - if (error != N_TXTADDR(ex)) { - send_sig(SIGKILL, current, 0); - return error; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, - fd_offset + ex.a_text); - up_write(¤t->mm->mmap_sem); - if (error != N_DATADDR(ex)) { - send_sig(SIGKILL, current, 0); - return error; - } - } -beyond_if: - set_binfmt(&aout32_format); - - set_brk(current->mm->start_brk, current->mm->brk); - - /* Make sure STACK_TOP returns the right thing. */ - orig_thr_flags = current_thread_info()->flags; - current_thread_info()->flags |= _TIF_32BIT; - - retval = setup_arg_pages(bprm, STACK_TOP, EXSTACK_DEFAULT); - if (retval < 0) { - current_thread_info()->flags = orig_thr_flags; - - /* Someone check-me: is this error path enough? */ - send_sig(SIGKILL, current, 0); - return retval; - } - - current->mm->start_stack = - (unsigned long) create_aout32_tables((char __user *)bprm->p, bprm); - tsb_context_switch(current->mm); - - start_thread32(regs, ex.a_entry, current->mm->start_stack); - if (current->ptrace & PT_PTRACED) - send_sig(SIGTRAP, current, 0); - return 0; -} - -/* N.B. Move to .h file and use code in fs/binfmt_aout.c? */ -static int load_aout32_library(struct file *file) -{ - struct inode * inode; - unsigned long bss, start_addr, len; - unsigned long error; - int retval; - struct exec ex; - - inode = file->f_path.dentry->d_inode; - - retval = -ENOEXEC; - error = kernel_read(file, 0, (char *) &ex, sizeof(ex)); - if (error != sizeof(ex)) - goto out; - - /* We come in here for the regular a.out style of shared libraries */ - if ((N_MAGIC(ex) != ZMAGIC && N_MAGIC(ex) != QMAGIC) || N_TRSIZE(ex) || - N_DRSIZE(ex) || ((ex.a_entry & 0xfff) && N_MAGIC(ex) == ZMAGIC) || - inode->i_size < ex.a_text+ex.a_data+N_SYMSIZE(ex)+N_TXTOFF(ex)) { - goto out; - } - - if (N_MAGIC(ex) == ZMAGIC && N_TXTOFF(ex) && - (N_TXTOFF(ex) < inode->i_sb->s_blocksize)) { - printk("N_TXTOFF < BLOCK_SIZE. Please convert library\n"); - goto out; - } - - if (N_FLAGS(ex)) - goto out; - - /* For QMAGIC, the starting address is 0x20 into the page. We mask - this off to get the starting address for the page */ - - start_addr = ex.a_entry & 0xfffff000; - - /* Now use mmap to map the library into memory. */ - down_write(¤t->mm->mmap_sem); - error = do_mmap(file, start_addr, ex.a_text + ex.a_data, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, - N_TXTOFF(ex)); - up_write(¤t->mm->mmap_sem); - retval = error; - if (error != start_addr) - goto out; - - len = PAGE_ALIGN(ex.a_text + ex.a_data); - bss = ex.a_text + ex.a_data + ex.a_bss; - if (bss > len) { - down_write(¤t->mm->mmap_sem); - error = do_brk(start_addr + len, bss - len); - up_write(¤t->mm->mmap_sem); - retval = error; - if (error != start_addr + len) - goto out; - } - retval = 0; -out: - return retval; -} - -static int __init init_aout32_binfmt(void) -{ - return register_binfmt(&aout32_format); -} - -static void __exit exit_aout32_binfmt(void) -{ - unregister_binfmt(&aout32_format); -} - -module_init(init_aout32_binfmt); -module_exit(exit_aout32_binfmt); diff --git a/arch/sparc64/kernel/entry.S b/arch/sparc64/kernel/entry.S index 49eca4b1cf25..fb43c76bdc26 100644 --- a/arch/sparc64/kernel/entry.S +++ b/arch/sparc64/kernel/entry.S @@ -1353,63 +1353,6 @@ breakpoint_trap: ba,pt %xcc, rtrap nop -#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ - defined(CONFIG_SOLARIS_EMUL_MODULE) - /* SunOS uses syscall zero as the 'indirect syscall' it looks - * like indir_syscall(scall_num, arg0, arg1, arg2...); etc. - * This is complete brain damage. - */ - .globl sunos_indir -sunos_indir: - srl %o0, 0, %o0 - mov %o7, %l4 - cmp %o0, NR_SYSCALLS - blu,a,pt %icc, 1f - sll %o0, 0x2, %o0 - sethi %hi(sunos_nosys), %l6 - b,pt %xcc, 2f - or %l6, %lo(sunos_nosys), %l6 -1: sethi %hi(sunos_sys_table), %l7 - or %l7, %lo(sunos_sys_table), %l7 - lduw [%l7 + %o0], %l6 -2: mov %o1, %o0 - mov %o2, %o1 - mov %o3, %o2 - mov %o4, %o3 - mov %o5, %o4 - call %l6 - mov %l4, %o7 - - .globl sunos_getpid -sunos_getpid: - call sys_getppid - nop - call sys_getpid - stx %o0, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_sys_call - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - - /* SunOS getuid() returns uid in %o0 and euid in %o1 */ - .globl sunos_getuid -sunos_getuid: - call sys32_geteuid16 - nop - call sys32_getuid16 - stx %o0, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_sys_call - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - - /* SunOS getgid() returns gid in %o0 and egid in %o1 */ - .globl sunos_getgid -sunos_getgid: - call sys32_getegid16 - nop - call sys32_getgid16 - stx %o0, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_sys_call - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] -#endif - /* SunOS's execv() call only specifies the argv argument, the * environment settings are the same as the calling processes. */ @@ -1591,7 +1534,7 @@ linux_syscall_trace: mov %i4, %o4 - /* Linux 32-bit and SunOS system calls enter here... */ + /* Linux 32-bit system calls enter here... */ .align 32 .globl linux_sparc_syscall32 linux_sparc_syscall32: @@ -1614,7 +1557,7 @@ linux_sparc_syscall32: srl %i3, 0, %o3 ! IEU0 ba,a,pt %xcc, 3f - /* Linux native and SunOS system calls enter here... */ + /* Linux native system calls enter here... */ .align 32 .globl linux_sparc_syscall, ret_sys_call linux_sparc_syscall: diff --git a/arch/sparc64/kernel/signal.c b/arch/sparc64/kernel/signal.c index 9d51956e8e2f..1c47009eb5ec 100644 --- a/arch/sparc64/kernel/signal.c +++ b/arch/sparc64/kernel/signal.c @@ -25,7 +25,6 @@ #include #include -#include #include #include #include diff --git a/arch/sparc64/kernel/signal32.c b/arch/sparc64/kernel/signal32.c index 8c1c121330fb..74e0512f135c 100644 --- a/arch/sparc64/kernel/signal32.c +++ b/arch/sparc64/kernel/signal32.c @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -798,281 +797,6 @@ sigsegv: force_sigsegv(signo, current); } -/* Setup a Solaris stack frame */ -static void -setup_svr4_frame32(struct sigaction *sa, unsigned long pc, unsigned long npc, - struct pt_regs *regs, int signr, sigset_t *oldset) -{ - svr4_signal_frame_t __user *sfp; - svr4_gregset_t __user *gr; - svr4_siginfo_t __user *si; - svr4_mcontext_t __user *mc; - svr4_gwindows_t __user *gw; - svr4_ucontext_t __user *uc; - svr4_sigset_t setv; - unsigned int psr; - int i, err; - - synchronize_user_stack(); - save_and_clear_fpu(); - - regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL; - sfp = (svr4_signal_frame_t __user *) - get_sigframe(sa, regs, - sizeof(struct reg_window32) + SVR4_SF_ALIGNED); - - if (invalid_frame_pointer(sfp, sizeof(*sfp))) - do_exit(SIGILL); - - /* Start with a clean frame pointer and fill it */ - err = clear_user(sfp, sizeof(*sfp)); - - /* Setup convenience variables */ - si = &sfp->si; - uc = &sfp->uc; - gw = &sfp->gw; - mc = &uc->mcontext; - gr = &mc->greg; - - /* FIXME: where am I supposed to put this? - * sc->sigc_onstack = old_status; - * anyways, it does not look like it is used for anything at all. - */ - setv.sigbits[0] = oldset->sig[0]; - setv.sigbits[1] = (oldset->sig[0] >> 32); - if (_NSIG_WORDS >= 2) { - setv.sigbits[2] = oldset->sig[1]; - setv.sigbits[3] = (oldset->sig[1] >> 32); - err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); - } else - err |= __copy_to_user(&uc->sigmask, &setv, - 2 * sizeof(unsigned int)); - - /* Store registers */ - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - err |= __put_user(regs->tpc, &((*gr)[SVR4_PC])); - err |= __put_user(regs->tnpc, &((*gr)[SVR4_NPC])); - psr = tstate_to_psr(regs->tstate); - if (current_thread_info()->fpsaved[0] & FPRS_FEF) - psr |= PSR_EF; - err |= __put_user(psr, &((*gr)[SVR4_PSR])); - err |= __put_user(regs->y, &((*gr)[SVR4_Y])); - - /* Copy g[1..7] and o[0..7] registers */ - for (i = 0; i < 7; i++) - err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); - for (i = 0; i < 8; i++) - err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); - - /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &uc->stack.sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - err |= __put_user(current->sas_ss_size, &uc->stack.size); - - /* Save the currently window file: */ - - /* 1. Link sfp->uc->gwins to our windows */ - err |= __put_user(ptr_to_compat(gw), &mc->gwin); - - /* 2. Number of windows to restore at setcontext (): */ - err |= __put_user(get_thread_wsaved(), &gw->count); - - /* 3. We just pay attention to the gw->count field on setcontext */ - set_thread_wsaved(0); /* So process is allowed to execute. */ - - /* Setup the signal information. Solaris expects a bunch of - * information to be passed to the signal handler, we don't provide - * that much currently, should use siginfo. - */ - err |= __put_user(signr, &si->siginfo.signo); - err |= __put_user(SVR4_SINOINFO, &si->siginfo.code); - if (err) - goto sigsegv; - - regs->u_regs[UREG_FP] = (unsigned long) sfp; - regs->tpc = (unsigned long) sa->sa_handler; - regs->tnpc = (regs->tpc + 4); - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - - /* Arguments passed to signal handler */ - if (regs->u_regs[14]){ - struct reg_window32 __user *rw = (struct reg_window32 __user *) - (regs->u_regs[14] & 0x00000000ffffffffUL); - - err |= __put_user(signr, &rw->ins[0]); - err |= __put_user((u64)si, &rw->ins[1]); - err |= __put_user((u64)uc, &rw->ins[2]); - err |= __put_user((u64)sfp, &rw->ins[6]); /* frame pointer */ - if (err) - goto sigsegv; - - regs->u_regs[UREG_I0] = signr; - regs->u_regs[UREG_I1] = (u32)(u64) si; - regs->u_regs[UREG_I2] = (u32)(u64) uc; - } - return; - -sigsegv: - force_sigsegv(signr, current); -} - -asmlinkage int -svr4_getcontext(svr4_ucontext_t __user *uc, struct pt_regs *regs) -{ - svr4_gregset_t __user *gr; - svr4_mcontext_t __user *mc; - svr4_sigset_t setv; - int i, err; - u32 psr; - - synchronize_user_stack(); - save_and_clear_fpu(); - - if (get_thread_wsaved()) - do_exit(SIGSEGV); - - err = clear_user(uc, sizeof(*uc)); - - /* Setup convenience variables */ - mc = &uc->mcontext; - gr = &mc->greg; - - setv.sigbits[0] = current->blocked.sig[0]; - setv.sigbits[1] = (current->blocked.sig[0] >> 32); - if (_NSIG_WORDS >= 2) { - setv.sigbits[2] = current->blocked.sig[1]; - setv.sigbits[3] = (current->blocked.sig[1] >> 32); - err |= __copy_to_user(&uc->sigmask, &setv, sizeof(svr4_sigset_t)); - } else - err |= __copy_to_user(&uc->sigmask, &setv, 2 * sizeof(unsigned)); - - /* Store registers */ - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - err |= __put_user(regs->tpc, &uc->mcontext.greg[SVR4_PC]); - err |= __put_user(regs->tnpc, &uc->mcontext.greg[SVR4_NPC]); - - psr = tstate_to_psr(regs->tstate) & ~PSR_EF; - if (current_thread_info()->fpsaved[0] & FPRS_FEF) - psr |= PSR_EF; - err |= __put_user(psr, &uc->mcontext.greg[SVR4_PSR]); - - err |= __put_user(regs->y, &uc->mcontext.greg[SVR4_Y]); - - /* Copy g[1..7] and o[0..7] registers */ - for (i = 0; i < 7; i++) - err |= __put_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); - for (i = 0; i < 8; i++) - err |= __put_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); - - /* Setup sigaltstack */ - err |= __put_user(current->sas_ss_sp, &uc->stack.sp); - err |= __put_user(sas_ss_flags(regs->u_regs[UREG_FP]), &uc->stack.flags); - err |= __put_user(current->sas_ss_size, &uc->stack.size); - - /* The register file is not saved - * we have already stuffed all of it with sync_user_stack - */ - return (err ? -EFAULT : 0); -} - - -/* Set the context for a svr4 application, this is Solaris way to sigreturn */ -asmlinkage int svr4_setcontext(svr4_ucontext_t __user *c, struct pt_regs *regs) -{ - svr4_gregset_t __user *gr; - mm_segment_t old_fs; - u32 pc, npc, psr, u_ss_sp; - sigset_t set; - svr4_sigset_t setv; - int i, err; - stack_t st; - - /* Fixme: restore windows, or is this already taken care of in - * svr4_setup_frame when sync_user_windows is done? - */ - flush_user_windows(); - - if (get_thread_wsaved()) - goto sigsegv; - - if (((unsigned long) c) & 3){ - printk("Unaligned structure passed\n"); - goto sigsegv; - } - - if (!__access_ok(c, sizeof(*c))) { - /* Miguel, add nice debugging msg _here_. ;-) */ - goto sigsegv; - } - - /* Check for valid PC and nPC */ - gr = &c->mcontext.greg; - err = __get_user(pc, &((*gr)[SVR4_PC])); - err |= __get_user(npc, &((*gr)[SVR4_NPC])); - if ((pc | npc) & 3) - goto sigsegv; - - /* Retrieve information from passed ucontext */ - /* note that nPC is ored a 1, this is used to inform entry.S */ - /* that we don't want it to mess with our PC and nPC */ - - err |= copy_from_user(&setv, &c->sigmask, sizeof(svr4_sigset_t)); - set.sig[0] = setv.sigbits[0] | (((long)setv.sigbits[1]) << 32); - if (_NSIG_WORDS >= 2) - set.sig[1] = setv.sigbits[2] | (((long)setv.sigbits[3]) << 32); - - err |= __get_user(u_ss_sp, &c->stack.sp); - st.ss_sp = compat_ptr(u_ss_sp); - err |= __get_user(st.ss_flags, &c->stack.flags); - err |= __get_user(st.ss_size, &c->stack.size); - if (err) - goto sigsegv; - - /* It is more difficult to avoid calling this function than to - call it and ignore errors. */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - do_sigaltstack((stack_t __user *) &st, NULL, regs->u_regs[UREG_I6]); - set_fs(old_fs); - - sigdelsetmask(&set, ~_BLOCKABLE); - spin_lock_irq(¤t->sighand->siglock); - current->blocked = set; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - regs->tpc = pc; - regs->tnpc = npc | 1; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - err |= __get_user(regs->y, &((*gr)[SVR4_Y])); - err |= __get_user(psr, &((*gr)[SVR4_PSR])); - regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC); - regs->tstate |= psr_to_tstate_icc(psr); - - /* Restore g[1..7] and o[0..7] registers */ - for (i = 0; i < 7; i++) - err |= __get_user(regs->u_regs[UREG_G1+i], (&(*gr)[SVR4_G1])+i); - for (i = 0; i < 8; i++) - err |= __get_user(regs->u_regs[UREG_I0+i], (&(*gr)[SVR4_O0])+i); - if (err) - goto sigsegv; - - return -EINTR; -sigsegv: - return -EFAULT; -} - static void setup_rt_frame32(struct k_sigaction *ka, struct pt_regs *regs, unsigned long signr, sigset_t *oldset, siginfo_t *info) @@ -1216,20 +940,14 @@ sigsegv: static inline void handle_signal32(unsigned long signr, struct k_sigaction *ka, siginfo_t *info, - sigset_t *oldset, struct pt_regs *regs, - int svr4_signal) + sigset_t *oldset, struct pt_regs *regs) { - if (svr4_signal) - setup_svr4_frame32(&ka->sa, regs->tpc, regs->tnpc, - regs, signr, oldset); - else { - if (ka->sa.sa_flags & SA_SIGINFO) - setup_rt_frame32(ka, regs, signr, oldset, info); - else if (test_thread_flag(TIF_NEWSIGNALS)) - new_setup_frame32(ka, regs, signr, oldset); - else - setup_frame32(&ka->sa, regs, signr, oldset, info); - } + if (ka->sa.sa_flags & SA_SIGINFO) + setup_rt_frame32(ka, regs, signr, oldset, info); + else if (test_thread_flag(TIF_NEWSIGNALS)) + new_setup_frame32(ka, regs, signr, oldset); + else + setup_frame32(&ka->sa, regs, signr, oldset, info); spin_lock_irq(¤t->sighand->siglock); sigorsets(¤t->blocked,¤t->blocked,&ka->sa.sa_mask); if (!(ka->sa.sa_flags & SA_NOMASK)) @@ -1270,7 +988,6 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, struct signal_deliver_cookie cookie; struct k_sigaction ka; int signr; - int svr4_signal = current->personality == PER_SVR4; cookie.restart_syscall = restart_syscall; cookie.orig_i0 = orig_i0; @@ -1279,8 +996,7 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, if (signr > 0) { if (cookie.restart_syscall) syscall_restart32(orig_i0, regs, &ka.sa); - handle_signal32(signr, &ka, &info, oldset, - regs, svr4_signal); + handle_signal32(signr, &ka, &info, oldset, regs); /* a signal was successfully delivered; the saved * sigmask will have been stored in the signal frame, diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 051b8d9cb989..38736460b8db 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c @@ -33,13 +33,11 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include @@ -73,13 +71,8 @@ extern __kernel_size_t strlen(const char *); extern void linux_sparc_syscall(void); extern void rtrap(void); extern void show_regs(struct pt_regs *); -extern void solaris_syscall(void); extern void syscall_trace(struct pt_regs *, int); -extern u32 sunos_sys_table[], sys_call_table32[]; -extern void tl0_solaris(void); extern void sys_sigsuspend(void); -extern int svr4_getcontext(svr4_ucontext_t *uc, struct pt_regs *regs); -extern int svr4_setcontext(svr4_ucontext_t *uc, struct pt_regs *regs); extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); extern long sparc32_open(const char __user * filename, int flags, int mode); @@ -90,8 +83,6 @@ extern int __ashrdi3(int, int); extern int dump_fpu (struct pt_regs * regs, elf_fpregset_t * fpregs); -extern unsigned int sys_call_table[]; - extern void xor_vis_2(unsigned long, unsigned long *, unsigned long *); extern void xor_vis_3(unsigned long, unsigned long *, unsigned long *, unsigned long *); @@ -213,11 +204,6 @@ EXPORT_SYMBOL(pci_dma_supported); /* I/O device mmaping on Sparc64. */ EXPORT_SYMBOL(io_remap_pfn_range); -#if defined(CONFIG_COMPAT) && defined(CONFIG_NET) -/* Solaris/SunOS binary compatibility */ -EXPORT_SYMBOL(verify_compat_iovec); -#endif - EXPORT_SYMBOL(dump_fpu); EXPORT_SYMBOL(put_fs_struct); @@ -254,30 +240,6 @@ EXPORT_SYMBOL(strlen); EXPORT_SYMBOL(__strlen_user); EXPORT_SYMBOL(__strnlen_user); -#ifdef CONFIG_SOLARIS_EMUL_MODULE -EXPORT_SYMBOL(linux_sparc_syscall); -EXPORT_SYMBOL(rtrap); -EXPORT_SYMBOL(show_regs); -EXPORT_SYMBOL(solaris_syscall); -EXPORT_SYMBOL(syscall_trace); -EXPORT_SYMBOL(sunos_sys_table); -EXPORT_SYMBOL(sys_call_table32); -EXPORT_SYMBOL(tl0_solaris); -EXPORT_SYMBOL(sys_sigsuspend); -EXPORT_SYMBOL(sys_getppid); -EXPORT_SYMBOL(sys_getpid); -EXPORT_SYMBOL(sys_geteuid); -EXPORT_SYMBOL(sys_getuid); -EXPORT_SYMBOL(sys_getegid); -EXPORT_SYMBOL(sysctl_nr_open); -EXPORT_SYMBOL(sys_getgid); -EXPORT_SYMBOL(svr4_getcontext); -EXPORT_SYMBOL(svr4_setcontext); -EXPORT_SYMBOL(compat_sys_ioctl); -EXPORT_SYMBOL(sys_ioctl); -EXPORT_SYMBOL(sparc32_open); -#endif - /* Special internal versions of library functions. */ EXPORT_SYMBOL(_clear_page); EXPORT_SYMBOL(clear_user_page); @@ -334,9 +296,6 @@ EXPORT_SYMBOL(do_BUG); /* for ns8703 */ EXPORT_SYMBOL(ns87303_lock); -/* for solaris compat module */ -EXPORT_SYMBOL_GPL(sys_call_table); - EXPORT_SYMBOL(tick_ops); EXPORT_SYMBOL(xor_vis_2); diff --git a/arch/sparc64/kernel/sunos_ioctl32.c b/arch/sparc64/kernel/sunos_ioctl32.c deleted file mode 100644 index 75d2bad49839..000000000000 --- a/arch/sparc64/kernel/sunos_ioctl32.c +++ /dev/null @@ -1,275 +0,0 @@ -/* $Id: sunos_ioctl32.c,v 1.11 2000/07/30 23:12:24 davem Exp $ - * sunos_ioctl32.c: SunOS ioctl compatibility on sparc64. - * - * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) - * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define SUNOS_NR_OPEN 256 - -struct rtentry32 { - u32 rt_pad1; - struct sockaddr rt_dst; /* target address */ - struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */ - struct sockaddr rt_genmask; /* target network mask (IP) */ - unsigned short rt_flags; - short rt_pad2; - u32 rt_pad3; - unsigned char rt_tos; - unsigned char rt_class; - short rt_pad4; - short rt_metric; /* +1 for binary compatibility! */ - /* char * */ u32 rt_dev; /* forcing the device at add */ - u32 rt_mtu; /* per route MTU/Window */ - u32 rt_window; /* Window clamping */ - unsigned short rt_irtt; /* Initial RTT */ - -}; - -struct ifmap32 { - u32 mem_start; - u32 mem_end; - unsigned short base_addr; - unsigned char irq; - unsigned char dma; - unsigned char port; -}; - -struct ifreq32 { -#define IFHWADDRLEN 6 -#define IFNAMSIZ 16 - union { - char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */ - } ifr_ifrn; - union { - struct sockaddr ifru_addr; - struct sockaddr ifru_dstaddr; - struct sockaddr ifru_broadaddr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; - short ifru_flags; - int ifru_ivalue; - int ifru_mtu; - struct ifmap32 ifru_map; - char ifru_slave[IFNAMSIZ]; /* Just fits the size */ - compat_caddr_t ifru_data; - } ifr_ifru; -}; - -struct ifconf32 { - int ifc_len; /* size of buffer */ - compat_caddr_t ifcbuf; -}; - -extern asmlinkage int compat_sys_ioctl(unsigned int, unsigned int, u32); - -asmlinkage int sunos_ioctl (int fd, u32 cmd, u32 arg) -{ - int ret = -EBADF; - - if(fd >= SUNOS_NR_OPEN) - goto out; - if(!fcheck(fd)) - goto out; - - if(cmd == TIOCSETD) { - mm_segment_t old_fs = get_fs(); - int __user *p; - int ntty = N_TTY; - int tmp; - - p = (int __user *) (unsigned long) arg; - ret = -EFAULT; - if(get_user(tmp, p)) - goto out; - if(tmp == 2) { - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long) &ntty); - set_fs(old_fs); - ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); - goto out; - } - } - if(cmd == TIOCNOTTY) { - ret = sys_setsid(); - goto out; - } - switch(cmd) { - case _IOW('r', 10, struct rtentry32): - ret = compat_sys_ioctl(fd, SIOCADDRT, arg); - goto out; - case _IOW('r', 11, struct rtentry32): - ret = compat_sys_ioctl(fd, SIOCDELRT, arg); - goto out; - - case _IOW('i', 12, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFADDR, arg); - goto out; - case _IOWR('i', 13, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFADDR, arg); - goto out; - case _IOW('i', 14, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg); - goto out; - case _IOWR('i', 15, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg); - goto out; - case _IOW('i', 16, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFFLAGS, arg); - goto out; - case _IOWR('i', 17, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFFLAGS, arg); - goto out; - case _IOW('i', 18, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFMEM, arg); - goto out; - case _IOWR('i', 19, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFMEM, arg); - goto out; - - case _IOWR('i', 20, struct ifconf32): - ret = compat_sys_ioctl(fd, SIOCGIFCONF, arg); - goto out; - - case _IOW('i', 21, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFMTU, arg); - goto out; - - case _IOWR('i', 22, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFMTU, arg); - goto out; - - case _IOWR('i', 23, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg); - goto out; - case _IOW('i', 24, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg); - goto out; - case _IOWR('i', 25, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFNETMASK, arg); - goto out; - case _IOW('i', 26, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFNETMASK, arg); - goto out; - case _IOWR('i', 27, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCGIFMETRIC, arg); - goto out; - case _IOW('i', 28, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCSIFMETRIC, arg); - goto out; - - case _IOW('i', 30, struct arpreq): - ret = compat_sys_ioctl(fd, SIOCSARP, arg); - goto out; - case _IOWR('i', 31, struct arpreq): - ret = compat_sys_ioctl(fd, SIOCGARP, arg); - goto out; - case _IOW('i', 32, struct arpreq): - ret = compat_sys_ioctl(fd, SIOCDARP, arg); - goto out; - - case _IOW('i', 40, struct ifreq32): /* SIOCUPPER */ - case _IOW('i', 41, struct ifreq32): /* SIOCLOWER */ - case _IOW('i', 44, struct ifreq32): /* SIOCSETSYNC */ - case _IOW('i', 45, struct ifreq32): /* SIOCGETSYNC */ - case _IOW('i', 46, struct ifreq32): /* SIOCSSDSTATS */ - case _IOW('i', 47, struct ifreq32): /* SIOCSSESTATS */ - case _IOW('i', 48, struct ifreq32): /* SIOCSPROMISC */ - ret = -EOPNOTSUPP; - goto out; - - case _IOW('i', 49, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCADDMULTI, arg); - goto out; - case _IOW('i', 50, struct ifreq32): - ret = compat_sys_ioctl(fd, SIOCDELMULTI, arg); - goto out; - - /* FDDI interface ioctls, unsupported. */ - - case _IOW('i', 51, struct ifreq32): /* SIOCFDRESET */ - case _IOW('i', 52, struct ifreq32): /* SIOCFDSLEEP */ - case _IOW('i', 53, struct ifreq32): /* SIOCSTRTFMWAR */ - case _IOW('i', 54, struct ifreq32): /* SIOCLDNSTRTFW */ - case _IOW('i', 55, struct ifreq32): /* SIOCGETFDSTAT */ - case _IOW('i', 56, struct ifreq32): /* SIOCFDNMIINT */ - case _IOW('i', 57, struct ifreq32): /* SIOCFDEXUSER */ - case _IOW('i', 58, struct ifreq32): /* SIOCFDGNETMAP */ - case _IOW('i', 59, struct ifreq32): /* SIOCFDGIOCTL */ - printk("FDDI ioctl, returning EOPNOTSUPP\n"); - ret = -EOPNOTSUPP; - goto out; - - case _IOW('t', 125, int): - /* More stupid tty sunos ioctls, just - * say it worked. - */ - ret = 0; - goto out; - - /* Non posix grp */ - case _IOW('t', 118, int): { - int oldval, newval, __user *ptr; - - cmd = TIOCSPGRP; - ptr = (int __user *) (unsigned long) arg; - ret = -EFAULT; - if(get_user(oldval, ptr)) - goto out; - ret = compat_sys_ioctl(fd, cmd, arg); - __get_user(newval, ptr); - if(newval == -1) { - __put_user(oldval, ptr); - ret = -EIO; - } - if(ret == -ENOTTY) - ret = -EIO; - goto out; - } - - case _IOR('t', 119, int): { - int oldval, newval, __user *ptr; - - cmd = TIOCGPGRP; - ptr = (int __user *) (unsigned long) arg; - ret = -EFAULT; - if(get_user(oldval, ptr)) - goto out; - ret = compat_sys_ioctl(fd, cmd, arg); - __get_user(newval, ptr); - if(newval == -1) { - __put_user(oldval, ptr); - ret = -EIO; - } - if(ret == -ENOTTY) - ret = -EIO; - goto out; - } - }; - - ret = compat_sys_ioctl(fd, cmd, arg); - /* so stupid... */ - ret = (ret == -EINVAL ? -EOPNOTSUPP : ret); -out: - return ret; -} diff --git a/arch/sparc64/kernel/sys_sparc.c b/arch/sparc64/kernel/sys_sparc.c index f952745d0f3d..73ed01ba40dc 100644 --- a/arch/sparc64/kernel/sys_sparc.c +++ b/arch/sparc64/kernel/sys_sparc.c @@ -720,44 +720,6 @@ out: return err; } -asmlinkage long solaris_syscall(struct pt_regs *regs) -{ - static int count; - - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - if (++count <= 5) { - printk ("For Solaris binary emulation you need solaris module loaded\n"); - show_regs (regs); - } - send_sig(SIGSEGV, current, 1); - - return -ENOSYS; -} - -#ifndef CONFIG_SUNOS_EMUL -asmlinkage long sunos_syscall(struct pt_regs *regs) -{ - static int count; - - regs->tpc = regs->tnpc; - regs->tnpc += 4; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - if (++count <= 20) - printk ("SunOS binary emulation not compiled in\n"); - force_sig(SIGSEGV, current); - - return -ENOSYS; -} -#endif - asmlinkage long sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, utrap_handler_t new_d, diff --git a/arch/sparc64/kernel/sys_sunos32.c b/arch/sparc64/kernel/sys_sunos32.c deleted file mode 100644 index e91194fe39d7..000000000000 --- a/arch/sparc64/kernel/sys_sunos32.c +++ /dev/null @@ -1,1359 +0,0 @@ -/* $Id: sys_sunos32.c,v 1.64 2002/02/09 19:49:31 davem Exp $ - * sys_sunos32.c: SunOS binary compatibility layer on sparc64. - * - * Copyright (C) 1995, 1996, 1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) - * - * Based upon preliminary work which is: - * - * Copyright (C) 1995 Adrian M. Rodriguez (adrian@remus.rutgers.edu) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include /* for gethostid() */ -#include -#include -#include - -/* For the nfs mount emulation */ -#include -#include -#include -#include -#include - -/* for sunos_select */ -#include -#include - -/* For SOCKET_I */ -#include -#include - -#define SUNOS_NR_OPEN 256 - -asmlinkage u32 sunos_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off) -{ - struct file *file = NULL; - unsigned long retval, ret_type; - - if (flags & MAP_NORESERVE) { - static int cnt; - if (cnt++ < 10) - printk("%s: unimplemented SunOS MAP_NORESERVE mmap() flag\n", - current->comm); - flags &= ~MAP_NORESERVE; - } - retval = -EBADF; - if (!(flags & MAP_ANONYMOUS)) { - struct inode * inode; - if (fd >= SUNOS_NR_OPEN) - goto out; - file = fget(fd); - if (!file) - goto out; - inode = file->f_path.dentry->d_inode; - if (imajor(inode) == MEM_MAJOR && iminor(inode) == 5) { - flags |= MAP_ANONYMOUS; - fput(file); - file = NULL; - } - } - - retval = -EINVAL; - if (!(flags & MAP_FIXED)) - addr = 0; - else if (len > 0xf0000000 || addr > 0xf0000000 - len) - goto out_putf; - ret_type = flags & _MAP_NEW; - flags &= ~_MAP_NEW; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - down_write(¤t->mm->mmap_sem); - retval = do_mmap(file, - (unsigned long) addr, (unsigned long) len, - (unsigned long) prot, (unsigned long) flags, - (unsigned long) off); - up_write(¤t->mm->mmap_sem); - if (!ret_type) - retval = ((retval < 0xf0000000) ? 0 : retval); -out_putf: - if (file) - fput(file); -out: - return (u32) retval; -} - -asmlinkage int sunos_mctl(u32 addr, u32 len, int function, u32 arg) -{ - return 0; -} - -asmlinkage int sunos_brk(u32 baddr) -{ - int freepages, retval = -ENOMEM; - unsigned long rlim; - unsigned long newbrk, oldbrk, brk = (unsigned long) baddr; - - down_write(¤t->mm->mmap_sem); - if (brk < current->mm->end_code) - goto out; - newbrk = PAGE_ALIGN(brk); - oldbrk = PAGE_ALIGN(current->mm->brk); - retval = 0; - if (oldbrk == newbrk) { - current->mm->brk = brk; - goto out; - } - /* Always allow shrinking brk. */ - if (brk <= current->mm->brk) { - current->mm->brk = brk; - do_munmap(current->mm, newbrk, oldbrk-newbrk); - goto out; - } - /* Check against rlimit and stack.. */ - retval = -ENOMEM; - rlim = current->signal->rlim[RLIMIT_DATA].rlim_cur; - if (rlim >= RLIM_INFINITY) - rlim = ~0; - if (brk - current->mm->end_code > rlim) - goto out; - /* Check against existing mmap mappings. */ - if (find_vma_intersection(current->mm, oldbrk, newbrk+PAGE_SIZE)) - goto out; - /* stupid algorithm to decide if we have enough memory: while - * simple, it hopefully works in most obvious cases.. Easy to - * fool it, but this should catch most mistakes. - */ - freepages = global_page_state(NR_FILE_PAGES); - freepages >>= 1; - freepages += nr_free_pages(); - freepages += nr_swap_pages; - freepages -= num_physpages >> 4; - freepages -= (newbrk-oldbrk) >> PAGE_SHIFT; - if (freepages < 0) - goto out; - /* Ok, we have probably got enough memory - let it rip. */ - current->mm->brk = brk; - do_brk(oldbrk, newbrk-oldbrk); - retval = 0; -out: - up_write(¤t->mm->mmap_sem); - return retval; -} - -asmlinkage u32 sunos_sbrk(int increment) -{ - int error, oldbrk; - - /* This should do it hopefully... */ - oldbrk = (int)current->mm->brk; - error = sunos_brk(((int) current->mm->brk) + increment); - if (!error) - error = oldbrk; - return error; -} - -asmlinkage u32 sunos_sstk(int increment) -{ - printk("%s: Call to sunos_sstk(increment<%d>) is unsupported\n", - current->comm, increment); - - return (u32)-1; -} - -/* Give hints to the kernel as to what paging strategy to use... - * Completely bogus, don't remind me. - */ -#define VA_NORMAL 0 /* Normal vm usage expected */ -#define VA_ABNORMAL 1 /* Abnormal/random vm usage probable */ -#define VA_SEQUENTIAL 2 /* Accesses will be of a sequential nature */ -#define VA_INVALIDATE 3 /* Page table entries should be flushed ??? */ -static char *vstrings[] = { - "VA_NORMAL", - "VA_ABNORMAL", - "VA_SEQUENTIAL", - "VA_INVALIDATE", -}; - -asmlinkage void sunos_vadvise(u32 strategy) -{ - static int count; - - /* I wanna see who uses this... */ - if (count++ < 5) - printk("%s: Advises us to use %s paging strategy\n", - current->comm, - strategy <= 3 ? vstrings[strategy] : "BOGUS"); -} - -/* This just wants the soft limit (ie. rlim_cur element) of the RLIMIT_NOFILE - * resource limit and is for backwards compatibility with older sunos - * revs. - */ -asmlinkage int sunos_getdtablesize(void) -{ - return SUNOS_NR_OPEN; -} - - -#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP))) - -asmlinkage u32 sunos_sigblock(u32 blk_mask) -{ - u32 old; - - spin_lock_irq(¤t->sighand->siglock); - old = (u32) current->blocked.sig[0]; - current->blocked.sig[0] |= (blk_mask & _BLOCKABLE); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return old; -} - -asmlinkage u32 sunos_sigsetmask(u32 newmask) -{ - u32 retval; - - spin_lock_irq(¤t->sighand->siglock); - retval = (u32) current->blocked.sig[0]; - current->blocked.sig[0] = (newmask & _BLOCKABLE); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return retval; -} - -/* SunOS getdents is very similar to the newer Linux (iBCS2 compliant) */ -/* getdents system call, the format of the structure just has a different */ -/* layout (d_off+d_ino instead of d_ino+d_off) */ -struct sunos_dirent { - s32 d_off; - u32 d_ino; - u16 d_reclen; - u16 d_namlen; - char d_name[1]; -}; - -struct sunos_dirent_callback { - struct sunos_dirent __user *curr; - struct sunos_dirent __user *previous; - int count; - int error; -}; - -#define NAME_OFFSET(de) ((int) ((de)->d_name - (char __user *) (de))) -#define ROUND_UP(x) (((x)+sizeof(s32)-1) & ~(sizeof(s32)-1)) - -static int sunos_filldir(void * __buf, const char * name, int namlen, - loff_t offset, ino_t ino, unsigned int d_type) -{ - struct sunos_dirent __user *dirent; - struct sunos_dirent_callback * buf = (struct sunos_dirent_callback *) __buf; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); - u32 d_ino; - - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; - d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) - return -EOVERFLOW; - dirent = buf->previous; - if (dirent) - put_user(offset, &dirent->d_off); - dirent = buf->curr; - buf->previous = dirent; - put_user(d_ino, &dirent->d_ino); - put_user(namlen, &dirent->d_namlen); - put_user(reclen, &dirent->d_reclen); - if (copy_to_user(dirent->d_name, name, namlen)) - return -EFAULT; - put_user(0, dirent->d_name + namlen); - dirent = (void __user *) dirent + reclen; - buf->curr = dirent; - buf->count -= reclen; - return 0; -} - -asmlinkage int sunos_getdents(unsigned int fd, void __user *dirent, int cnt) -{ - struct file * file; - struct sunos_dirent __user *lastdirent; - struct sunos_dirent_callback buf; - int error = -EBADF; - - if (fd >= SUNOS_NR_OPEN) - goto out; - - file = fget(fd); - if (!file) - goto out; - - error = -EINVAL; - if (cnt < (sizeof(struct sunos_dirent) + 255)) - goto out_putf; - - buf.curr = (struct sunos_dirent __user *) dirent; - buf.previous = NULL; - buf.count = cnt; - buf.error = 0; - - error = vfs_readdir(file, sunos_filldir, &buf); - if (error < 0) - goto out_putf; - - lastdirent = buf.previous; - error = buf.error; - if (lastdirent) { - put_user(file->f_pos, &lastdirent->d_off); - error = cnt - buf.count; - } - -out_putf: - fput(file); -out: - return error; -} - -/* Old sunos getdirentries, severely broken compatibility stuff here. */ -struct sunos_direntry { - u32 d_ino; - u16 d_reclen; - u16 d_namlen; - char d_name[1]; -}; - -struct sunos_direntry_callback { - struct sunos_direntry __user *curr; - struct sunos_direntry __user *previous; - int count; - int error; -}; - -static int sunos_filldirentry(void * __buf, const char * name, int namlen, - loff_t offset, ino_t ino, unsigned int d_type) -{ - struct sunos_direntry __user *dirent; - struct sunos_direntry_callback * buf = - (struct sunos_direntry_callback *) __buf; - int reclen = ROUND_UP(NAME_OFFSET(dirent) + namlen + 1); - u32 d_ino; - - buf->error = -EINVAL; /* only used if we fail.. */ - if (reclen > buf->count) - return -EINVAL; - d_ino = ino; - if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) - return -EOVERFLOW; - dirent = buf->previous; - dirent = buf->curr; - buf->previous = dirent; - put_user(d_ino, &dirent->d_ino); - put_user(namlen, &dirent->d_namlen); - put_user(reclen, &dirent->d_reclen); - if (copy_to_user(dirent->d_name, name, namlen)) - return -EFAULT; - put_user(0, dirent->d_name + namlen); - dirent = (void __user *) dirent + reclen; - buf->curr = dirent; - buf->count -= reclen; - return 0; -} - -asmlinkage int sunos_getdirentries(unsigned int fd, - void __user *dirent, - int cnt, - unsigned int __user *basep) -{ - struct file * file; - struct sunos_direntry __user *lastdirent; - int error = -EBADF; - struct sunos_direntry_callback buf; - - if (fd >= SUNOS_NR_OPEN) - goto out; - - file = fget(fd); - if (!file) - goto out; - - error = -EINVAL; - if (cnt < (sizeof(struct sunos_direntry) + 255)) - goto out_putf; - - buf.curr = (struct sunos_direntry __user *) dirent; - buf.previous = NULL; - buf.count = cnt; - buf.error = 0; - - error = vfs_readdir(file, sunos_filldirentry, &buf); - if (error < 0) - goto out_putf; - - lastdirent = buf.previous; - error = buf.error; - if (lastdirent) { - put_user(file->f_pos, basep); - error = cnt - buf.count; - } - -out_putf: - fput(file); -out: - return error; -} - -struct sunos_utsname { - char sname[9]; - char nname[9]; - char nnext[56]; - char rel[9]; - char ver[9]; - char mach[9]; -}; - -asmlinkage int sunos_uname(struct sunos_utsname __user *name) -{ - int ret; - - down_read(&uts_sem); - ret = copy_to_user(&name->sname[0], &utsname()->sysname[0], - sizeof(name->sname) - 1); - ret |= copy_to_user(&name->nname[0], &utsname()->nodename[0], - sizeof(name->nname) - 1); - ret |= put_user('\0', &name->nname[8]); - ret |= copy_to_user(&name->rel[0], &utsname()->release[0], - sizeof(name->rel) - 1); - ret |= copy_to_user(&name->ver[0], &utsname()->version[0], - sizeof(name->ver) - 1); - ret |= copy_to_user(&name->mach[0], &utsname()->machine[0], - sizeof(name->mach) - 1); - up_read(&uts_sem); - return (ret ? -EFAULT : 0); -} - -asmlinkage int sunos_nosys(void) -{ - struct pt_regs *regs; - siginfo_t info; - static int cnt; - - regs = current_thread_info()->kregs; - if (test_thread_flag(TIF_32BIT)) { - regs->tpc &= 0xffffffff; - regs->tnpc &= 0xffffffff; - } - info.si_signo = SIGSYS; - info.si_errno = 0; - info.si_code = __SI_FAULT|0x100; - info.si_addr = (void __user *)regs->tpc; - info.si_trapno = regs->u_regs[UREG_G1]; - send_sig_info(SIGSYS, &info, current); - if (cnt++ < 4) { - printk("Process makes ni_syscall number %d, register dump:\n", - (int) regs->u_regs[UREG_G1]); - show_regs(regs); - } - return -ENOSYS; -} - -/* This is not a real and complete implementation yet, just to keep - * the easy SunOS binaries happy. - */ -asmlinkage int sunos_fpathconf(int fd, int name) -{ - int ret; - - switch(name) { - case _PCONF_LINK: - ret = LINK_MAX; - break; - case _PCONF_CANON: - ret = MAX_CANON; - break; - case _PCONF_INPUT: - ret = MAX_INPUT; - break; - case _PCONF_NAME: - ret = NAME_MAX; - break; - case _PCONF_PATH: - ret = PATH_MAX; - break; - case _PCONF_PIPE: - ret = PIPE_BUF; - break; - case _PCONF_CHRESTRICT: /* XXX Investigate XXX */ - ret = 1; - break; - case _PCONF_NOTRUNC: /* XXX Investigate XXX */ - case _PCONF_VDISABLE: - ret = 0; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -asmlinkage int sunos_pathconf(u32 u_path, int name) -{ - int ret; - - ret = sunos_fpathconf(0, name); /* XXX cheese XXX */ - return ret; -} - -asmlinkage int sunos_select(int width, u32 inp, u32 outp, u32 exp, u32 tvp_x) -{ - int ret; - - /* SunOS binaries expect that select won't change the tvp contents */ - ret = compat_sys_select(width, compat_ptr(inp), compat_ptr(outp), - compat_ptr(exp), compat_ptr(tvp_x)); - if (ret == -EINTR && tvp_x) { - struct compat_timeval __user *tvp = compat_ptr(tvp_x); - time_t sec, usec; - - __get_user(sec, &tvp->tv_sec); - __get_user(usec, &tvp->tv_usec); - if (sec == 0 && usec == 0) - ret = 0; - } - return ret; -} - -asmlinkage void sunos_nop(void) -{ - return; -} - -#if 0 /* This code doesn't translate user pointers correctly, - * disable for now. -DaveM - */ - -/* XXXXXXXXXX SunOS mount/umount. XXXXXXXXXXX */ -#define SMNT_RDONLY 1 -#define SMNT_NOSUID 2 -#define SMNT_NEWTYPE 4 -#define SMNT_GRPID 8 -#define SMNT_REMOUNT 16 -#define SMNT_NOSUB 32 -#define SMNT_MULTI 64 -#define SMNT_SYS5 128 - -struct sunos_fh_t { - char fh_data [NFS_FHSIZE]; -}; - -struct sunos_nfs_mount_args { - struct sockaddr_in *addr; /* file server address */ - struct nfs_fh *fh; /* File handle to be mounted */ - int flags; /* flags */ - int wsize; /* write size in bytes */ - int rsize; /* read size in bytes */ - int timeo; /* initial timeout in .1 secs */ - int retrans; /* times to retry send */ - char *hostname; /* server's hostname */ - int acregmin; /* attr cache file min secs */ - int acregmax; /* attr cache file max secs */ - int acdirmin; /* attr cache dir min secs */ - int acdirmax; /* attr cache dir max secs */ - char *netname; /* server's netname */ -}; - - -/* Bind the socket on a local reserved port and connect it to the - * remote server. This on Linux/i386 is done by the mount program, - * not by the kernel. - */ -/* XXXXXXXXXXXXXXXXXXXX */ -static int -sunos_nfs_get_server_fd (int fd, struct sockaddr_in *addr) -{ - struct sockaddr_in local; - struct sockaddr_in server; - int try_port; - int ret; - struct socket *socket; - struct inode *inode; - struct file *file; - - file = fget(fd); - if (!file) - return 0; - - inode = file->f_path.dentry->d_inode; - - socket = SOCKET_I(inode); - local.sin_family = AF_INET; - local.sin_addr.s_addr = htonl(INADDR_ANY); - - /* IPPORT_RESERVED = 1024, can't find the definition in the kernel */ - try_port = 1024; - do { - local.sin_port = htons (--try_port); - ret = socket->ops->bind(socket, (struct sockaddr*)&local, - sizeof(local)); - } while (ret && try_port > (1024 / 2)); - - if (ret) { - fput(file); - return 0; - } - - server.sin_family = AF_INET; - server.sin_addr = addr->sin_addr; - server.sin_port = NFS_PORT; - - /* Call sys_connect */ - ret = socket->ops->connect (socket, (struct sockaddr *) &server, - sizeof (server), file->f_flags); - fput(file); - if (ret < 0) - return 0; - return 1; -} - -/* XXXXXXXXXXXXXXXXXXXX */ -static int get_default (int value, int def_value) -{ - if (value) - return value; - else - return def_value; -} - -/* XXXXXXXXXXXXXXXXXXXX */ -static int sunos_nfs_mount(char *dir_name, int linux_flags, void __user *data) -{ - int server_fd, err; - char *the_name, *mount_page; - struct nfs_mount_data linux_nfs_mount; - struct sunos_nfs_mount_args sunos_mount; - - /* Ok, here comes the fun part: Linux's nfs mount needs a - * socket connection to the server, but SunOS mount does not - * require this, so we use the information on the destination - * address to create a socket and bind it to a reserved - * port on this system - */ - if (copy_from_user(&sunos_mount, data, sizeof(sunos_mount))) - return -EFAULT; - - server_fd = sys_socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (server_fd < 0) - return -ENXIO; - - if (copy_from_user(&linux_nfs_mount.addr, sunos_mount.addr, - sizeof(*sunos_mount.addr)) || - copy_from_user(&linux_nfs_mount.root, sunos_mount.fh, - sizeof(*sunos_mount.fh))) { - sys_close (server_fd); - return -EFAULT; - } - - if (!sunos_nfs_get_server_fd (server_fd, &linux_nfs_mount.addr)){ - sys_close (server_fd); - return -ENXIO; - } - - /* Now, bind it to a locally reserved port */ - linux_nfs_mount.version = NFS_MOUNT_VERSION; - linux_nfs_mount.flags = sunos_mount.flags; - linux_nfs_mount.fd = server_fd; - - linux_nfs_mount.rsize = get_default (sunos_mount.rsize, 8192); - linux_nfs_mount.wsize = get_default (sunos_mount.wsize, 8192); - linux_nfs_mount.timeo = get_default (sunos_mount.timeo, 10); - linux_nfs_mount.retrans = sunos_mount.retrans; - - linux_nfs_mount.acregmin = sunos_mount.acregmin; - linux_nfs_mount.acregmax = sunos_mount.acregmax; - linux_nfs_mount.acdirmin = sunos_mount.acdirmin; - linux_nfs_mount.acdirmax = sunos_mount.acdirmax; - - the_name = getname(sunos_mount.hostname); - if (IS_ERR(the_name)) - return PTR_ERR(the_name); - - strlcpy(linux_nfs_mount.hostname, the_name, - sizeof(linux_nfs_mount.hostname)); - putname (the_name); - - mount_page = (char *) get_zeroed_page(GFP_KERNEL); - if (!mount_page) - return -ENOMEM; - - memcpy(mount_page, &linux_nfs_mount, sizeof(linux_nfs_mount)); - - err = do_mount("", dir_name, "nfs", linux_flags, mount_page); - - free_page((unsigned long) mount_page); - return err; -} - -/* XXXXXXXXXXXXXXXXXXXX */ -asmlinkage int -sunos_mount(char *type, char *dir, int flags, void *data) -{ - int linux_flags = 0; - int ret = -EINVAL; - char *dev_fname = 0; - char *dir_page, *type_page; - - if (!capable (CAP_SYS_ADMIN)) - return -EPERM; - - /* We don't handle the integer fs type */ - if ((flags & SMNT_NEWTYPE) == 0) - goto out; - - /* Do not allow for those flags we don't support */ - if (flags & (SMNT_GRPID|SMNT_NOSUB|SMNT_MULTI|SMNT_SYS5)) - goto out; - - if (flags & SMNT_REMOUNT) - linux_flags |= MS_REMOUNT; - if (flags & SMNT_RDONLY) - linux_flags |= MS_RDONLY; - if (flags & SMNT_NOSUID) - linux_flags |= MS_NOSUID; - - dir_page = getname(dir); - ret = PTR_ERR(dir_page); - if (IS_ERR(dir_page)) - goto out; - - type_page = getname(type); - ret = PTR_ERR(type_page); - if (IS_ERR(type_page)) - goto out1; - - if (strcmp(type_page, "ext2") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "iso9660") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "minix") == 0) { - dev_fname = getname(data); - } else if (strcmp(type_page, "nfs") == 0) { - ret = sunos_nfs_mount (dir_page, flags, data); - goto out2; - } else if (strcmp(type_page, "ufs") == 0) { - printk("Warning: UFS filesystem mounts unsupported.\n"); - ret = -ENODEV; - goto out2; - } else if (strcmp(type_page, "proc")) { - ret = -ENODEV; - goto out2; - } - ret = PTR_ERR(dev_fname); - if (IS_ERR(dev_fname)) - goto out2; - lock_kernel(); - ret = do_mount(dev_fname, dir_page, type_page, linux_flags, NULL); - unlock_kernel(); - if (dev_fname) - putname(dev_fname); -out2: - putname(type_page); -out1: - putname(dir_page); -out: - return ret; -} -#endif - -asmlinkage int sunos_setpgrp(pid_t pid, pid_t pgid) -{ - int ret; - - /* So stupid... */ - if ((!pid || pid == current->pid) && - !pgid) { - sys_setsid(); - ret = 0; - } else { - ret = sys_setpgid(pid, pgid); - } - return ret; -} - -/* So stupid... */ -extern long compat_sys_wait4(compat_pid_t, compat_uint_t __user *, int, - struct compat_rusage __user *); - -asmlinkage int sunos_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options, struct compat_rusage __user *ru) -{ - int ret; - - ret = compat_sys_wait4((pid ? pid : ((compat_pid_t)-1)), - stat_addr, options, ru); - return ret; -} - -asmlinkage int sunos_killpg(int pgrp, int sig) -{ - int ret; - - rcu_read_lock(); - ret = -EINVAL; - if (pgrp > 0) - ret = kill_pgrp(find_vpid(pgrp), sig, 0); - rcu_read_unlock(); - - return ret; -} - -asmlinkage int sunos_audit(void) -{ - printk ("sys_audit\n"); - return -1; -} - -asmlinkage u32 sunos_gethostid(void) -{ - u32 ret; - - ret = (((u32)idprom->id_machtype << 24) | ((u32)idprom->id_sernum)); - - return ret; -} - -/* sysconf options, for SunOS compatibility */ -#define _SC_ARG_MAX 1 -#define _SC_CHILD_MAX 2 -#define _SC_CLK_TCK 3 -#define _SC_NGROUPS_MAX 4 -#define _SC_OPEN_MAX 5 -#define _SC_JOB_CONTROL 6 -#define _SC_SAVED_IDS 7 -#define _SC_VERSION 8 - -asmlinkage s32 sunos_sysconf (int name) -{ - s32 ret; - - switch (name){ - case _SC_ARG_MAX: - ret = ARG_MAX; - break; - case _SC_CHILD_MAX: - ret = current->signal->rlim[RLIMIT_NPROC].rlim_cur; - break; - case _SC_CLK_TCK: - ret = HZ; - break; - case _SC_NGROUPS_MAX: - ret = NGROUPS_MAX; - break; - case _SC_OPEN_MAX: - ret = current->signal->rlim[RLIMIT_NOFILE].rlim_cur; - break; - case _SC_JOB_CONTROL: - ret = 1; /* yes, we do support job control */ - break; - case _SC_SAVED_IDS: - ret = 1; /* yes, we do support saved uids */ - break; - case _SC_VERSION: - /* mhm, POSIX_VERSION is in /usr/include/unistd.h - * should it go on /usr/include/linux? - */ - ret = 199009; - break; - default: - ret = -1; - break; - }; - return ret; -} - -asmlinkage int sunos_semsys(int op, u32 arg1, u32 arg2, u32 arg3, void __user *ptr) -{ - union semun arg4; - int ret; - - switch (op) { - case 0: - /* Most arguments match on a 1:1 basis but cmd doesn't */ - switch(arg3) { - case 4: - arg3=GETPID; break; - case 5: - arg3=GETVAL; break; - case 6: - arg3=GETALL; break; - case 3: - arg3=GETNCNT; break; - case 7: - arg3=GETZCNT; break; - case 8: - arg3=SETVAL; break; - case 9: - arg3=SETALL; break; - } - /* sys_semctl(): */ - /* value to modify semaphore to */ - arg4.__pad = ptr; - ret = sys_semctl((int)arg1, (int)arg2, (int)arg3, arg4); - break; - case 1: - /* sys_semget(): */ - ret = sys_semget((key_t)arg1, (int)arg2, (int)arg3); - break; - case 2: - /* sys_semop(): */ - ret = sys_semop((int)arg1, (struct sembuf __user *)(unsigned long)arg2, - (unsigned int) arg3); - break; - default: - ret = -EINVAL; - break; - }; - return ret; -} - -struct msgbuf32 { - s32 mtype; - char mtext[1]; -}; - -struct ipc_perm32 -{ - key_t key; - compat_uid_t uid; - compat_gid_t gid; - compat_uid_t cuid; - compat_gid_t cgid; - compat_mode_t mode; - unsigned short seq; -}; - -struct msqid_ds32 -{ - struct ipc_perm32 msg_perm; - u32 msg_first; - u32 msg_last; - compat_time_t msg_stime; - compat_time_t msg_rtime; - compat_time_t msg_ctime; - u32 wwait; - u32 rwait; - unsigned short msg_cbytes; - unsigned short msg_qnum; - unsigned short msg_qbytes; - compat_ipc_pid_t msg_lspid; - compat_ipc_pid_t msg_lrpid; -}; - -static inline int sunos_msqid_get(struct msqid_ds32 __user *user, - struct msqid_ds *kern) -{ - if (get_user(kern->msg_perm.key, &user->msg_perm.key) || - __get_user(kern->msg_perm.uid, &user->msg_perm.uid) || - __get_user(kern->msg_perm.gid, &user->msg_perm.gid) || - __get_user(kern->msg_perm.cuid, &user->msg_perm.cuid) || - __get_user(kern->msg_perm.cgid, &user->msg_perm.cgid) || - __get_user(kern->msg_stime, &user->msg_stime) || - __get_user(kern->msg_rtime, &user->msg_rtime) || - __get_user(kern->msg_ctime, &user->msg_ctime) || - __get_user(kern->msg_ctime, &user->msg_cbytes) || - __get_user(kern->msg_ctime, &user->msg_qnum) || - __get_user(kern->msg_ctime, &user->msg_qbytes) || - __get_user(kern->msg_ctime, &user->msg_lspid) || - __get_user(kern->msg_ctime, &user->msg_lrpid)) - return -EFAULT; - return 0; -} - -static inline int sunos_msqid_put(struct msqid_ds32 __user *user, - struct msqid_ds *kern) -{ - if (put_user(kern->msg_perm.key, &user->msg_perm.key) || - __put_user(kern->msg_perm.uid, &user->msg_perm.uid) || - __put_user(kern->msg_perm.gid, &user->msg_perm.gid) || - __put_user(kern->msg_perm.cuid, &user->msg_perm.cuid) || - __put_user(kern->msg_perm.cgid, &user->msg_perm.cgid) || - __put_user(kern->msg_stime, &user->msg_stime) || - __put_user(kern->msg_rtime, &user->msg_rtime) || - __put_user(kern->msg_ctime, &user->msg_ctime) || - __put_user(kern->msg_ctime, &user->msg_cbytes) || - __put_user(kern->msg_ctime, &user->msg_qnum) || - __put_user(kern->msg_ctime, &user->msg_qbytes) || - __put_user(kern->msg_ctime, &user->msg_lspid) || - __put_user(kern->msg_ctime, &user->msg_lrpid)) - return -EFAULT; - return 0; -} - -static inline int sunos_msgbuf_get(struct msgbuf32 __user *user, struct msgbuf *kern, int len) -{ - if (get_user(kern->mtype, &user->mtype) || - __copy_from_user(kern->mtext, &user->mtext, len)) - return -EFAULT; - return 0; -} - -static inline int sunos_msgbuf_put(struct msgbuf32 __user *user, struct msgbuf *kern, int len) -{ - if (put_user(kern->mtype, &user->mtype) || - __copy_to_user(user->mtext, kern->mtext, len)) - return -EFAULT; - return 0; -} - -asmlinkage int sunos_msgsys(int op, u32 arg1, u32 arg2, u32 arg3, u32 arg4) -{ - struct sparc_stackf32 __user *sp; - struct msqid_ds kds; - struct msgbuf *kmbuf; - mm_segment_t old_fs = get_fs(); - u32 arg5; - int rval; - - switch(op) { - case 0: - rval = sys_msgget((key_t)arg1, (int)arg2); - break; - case 1: - if (!sunos_msqid_get((struct msqid_ds32 __user *)(unsigned long)arg3, &kds)) { - set_fs(KERNEL_DS); - rval = sys_msgctl((int)arg1, (int)arg2, - (struct msqid_ds __user *)(unsigned long)arg3); - set_fs(old_fs); - if (!rval) - rval = sunos_msqid_put((struct msqid_ds32 __user *)(unsigned long)arg3, - &kds); - } else - rval = -EFAULT; - break; - case 2: - rval = -EFAULT; - kmbuf = kmalloc(sizeof(struct msgbuf) + arg3, - GFP_KERNEL); - if (!kmbuf) - break; - sp = (struct sparc_stackf32 __user *) - (current_thread_info()->kregs->u_regs[UREG_FP] & 0xffffffffUL); - if (get_user(arg5, &sp->xxargs[0])) { - rval = -EFAULT; - kfree(kmbuf); - break; - } - set_fs(KERNEL_DS); - rval = sys_msgrcv((int)arg1, (struct msgbuf __user *) kmbuf, - (size_t)arg3, - (long)arg4, (int)arg5); - set_fs(old_fs); - if (!rval) - rval = sunos_msgbuf_put((struct msgbuf32 __user *)(unsigned long)arg2, - kmbuf, arg3); - kfree(kmbuf); - break; - case 3: - rval = -EFAULT; - kmbuf = kmalloc(sizeof(struct msgbuf) + arg3, - GFP_KERNEL); - if (!kmbuf || sunos_msgbuf_get((struct msgbuf32 __user *)(unsigned long)arg2, - kmbuf, arg3)) - break; - set_fs(KERNEL_DS); - rval = sys_msgsnd((int)arg1, (struct msgbuf __user *) kmbuf, - (size_t)arg3, (int)arg4); - set_fs(old_fs); - kfree(kmbuf); - break; - default: - rval = -EINVAL; - break; - } - return rval; -} - -struct shmid_ds32 { - struct ipc_perm32 shm_perm; - int shm_segsz; - compat_time_t shm_atime; - compat_time_t shm_dtime; - compat_time_t shm_ctime; - compat_ipc_pid_t shm_cpid; - compat_ipc_pid_t shm_lpid; - unsigned short shm_nattch; -}; - -static inline int sunos_shmid_get(struct shmid_ds32 __user *user, - struct shmid_ds *kern) -{ - if (get_user(kern->shm_perm.key, &user->shm_perm.key) || - __get_user(kern->shm_perm.uid, &user->shm_perm.uid) || - __get_user(kern->shm_perm.gid, &user->shm_perm.gid) || - __get_user(kern->shm_perm.cuid, &user->shm_perm.cuid) || - __get_user(kern->shm_perm.cgid, &user->shm_perm.cgid) || - __get_user(kern->shm_segsz, &user->shm_segsz) || - __get_user(kern->shm_atime, &user->shm_atime) || - __get_user(kern->shm_dtime, &user->shm_dtime) || - __get_user(kern->shm_ctime, &user->shm_ctime) || - __get_user(kern->shm_cpid, &user->shm_cpid) || - __get_user(kern->shm_lpid, &user->shm_lpid) || - __get_user(kern->shm_nattch, &user->shm_nattch)) - return -EFAULT; - return 0; -} - -static inline int sunos_shmid_put(struct shmid_ds32 __user *user, - struct shmid_ds *kern) -{ - if (put_user(kern->shm_perm.key, &user->shm_perm.key) || - __put_user(kern->shm_perm.uid, &user->shm_perm.uid) || - __put_user(kern->shm_perm.gid, &user->shm_perm.gid) || - __put_user(kern->shm_perm.cuid, &user->shm_perm.cuid) || - __put_user(kern->shm_perm.cgid, &user->shm_perm.cgid) || - __put_user(kern->shm_segsz, &user->shm_segsz) || - __put_user(kern->shm_atime, &user->shm_atime) || - __put_user(kern->shm_dtime, &user->shm_dtime) || - __put_user(kern->shm_ctime, &user->shm_ctime) || - __put_user(kern->shm_cpid, &user->shm_cpid) || - __put_user(kern->shm_lpid, &user->shm_lpid) || - __put_user(kern->shm_nattch, &user->shm_nattch)) - return -EFAULT; - return 0; -} - -asmlinkage int sunos_shmsys(int op, u32 arg1, u32 arg2, u32 arg3) -{ - struct shmid_ds ksds; - unsigned long raddr; - mm_segment_t old_fs = get_fs(); - int rval; - - switch(op) { - case 0: - /* do_shmat(): attach a shared memory area */ - rval = do_shmat((int)arg1,(char __user *)(unsigned long)arg2,(int)arg3,&raddr); - if (!rval) - rval = (int) raddr; - break; - case 1: - /* sys_shmctl(): modify shared memory area attr. */ - if (!sunos_shmid_get((struct shmid_ds32 __user *)(unsigned long)arg3, &ksds)) { - set_fs(KERNEL_DS); - rval = sys_shmctl((int) arg1,(int) arg2, - (struct shmid_ds __user *) &ksds); - set_fs(old_fs); - if (!rval) - rval = sunos_shmid_put((struct shmid_ds32 __user *)(unsigned long)arg3, - &ksds); - } else - rval = -EFAULT; - break; - case 2: - /* sys_shmdt(): detach a shared memory area */ - rval = sys_shmdt((char __user *)(unsigned long)arg1); - break; - case 3: - /* sys_shmget(): get a shared memory area */ - rval = sys_shmget((key_t)arg1,(int)arg2,(int)arg3); - break; - default: - rval = -EINVAL; - break; - }; - return rval; -} - -extern asmlinkage long sparc32_open(const char __user * filename, int flags, int mode); - -asmlinkage int sunos_open(u32 fname, int flags, int mode) -{ - const char __user *filename = compat_ptr(fname); - - return sparc32_open(filename, flags, mode); -} - -#define SUNOS_EWOULDBLOCK 35 - -/* see the sunos man page read(2v) for an explanation - of this garbage. We use O_NDELAY to mark - file descriptors that have been set non-blocking - using 4.2BSD style calls. (tridge) */ - -static inline int check_nonblock(int ret, int fd) -{ - if (ret == -EAGAIN) { - struct file * file = fget(fd); - if (file) { - if (file->f_flags & O_NDELAY) - ret = -SUNOS_EWOULDBLOCK; - fput(file); - } - } - return ret; -} - -asmlinkage int sunos_read(unsigned int fd, char __user *buf, u32 count) -{ - int ret; - - ret = check_nonblock(sys_read(fd, buf, count), fd); - return ret; -} - -asmlinkage int sunos_readv(u32 fd, void __user *vector, s32 count) -{ - int ret; - - ret = check_nonblock(compat_sys_readv(fd, vector, count), fd); - return ret; -} - -asmlinkage int sunos_write(unsigned int fd, char __user *buf, u32 count) -{ - int ret; - - ret = check_nonblock(sys_write(fd, buf, count), fd); - return ret; -} - -asmlinkage int sunos_writev(u32 fd, void __user *vector, s32 count) -{ - int ret; - - ret = check_nonblock(compat_sys_writev(fd, vector, count), fd); - return ret; -} - -asmlinkage int sunos_recv(u32 __fd, void __user *ubuf, int size, unsigned flags) -{ - int ret, fd = (int) __fd; - - ret = check_nonblock(sys_recv(fd, ubuf, size, flags), fd); - return ret; -} - -asmlinkage int sunos_send(u32 __fd, void __user *buff, int len, unsigned flags) -{ - int ret, fd = (int) __fd; - - ret = check_nonblock(sys_send(fd, buff, len, flags), fd); - return ret; -} - -asmlinkage int sunos_accept(u32 __fd, struct sockaddr __user *sa, int __user *addrlen) -{ - int ret, fd = (int) __fd; - - while (1) { - ret = check_nonblock(sys_accept(fd, sa, addrlen), fd); - if (ret != -ENETUNREACH && ret != -EHOSTUNREACH) - break; - } - return ret; -} - -#define SUNOS_SV_INTERRUPT 2 - -asmlinkage int sunos_sigaction (int sig, - struct old_sigaction32 __user *act, - struct old_sigaction32 __user *oact) -{ - struct k_sigaction new_ka, old_ka; - int ret; - - if (act) { - compat_old_sigset_t mask; - u32 u_handler; - - if (get_user(u_handler, &act->sa_handler) || - __get_user(new_ka.sa.sa_flags, &act->sa_flags)) - return -EFAULT; - new_ka.sa.sa_handler = compat_ptr(u_handler); - __get_user(mask, &act->sa_mask); - new_ka.sa.sa_restorer = NULL; - new_ka.ka_restorer = NULL; - siginitset(&new_ka.sa.sa_mask, mask); - new_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT; - } - - ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); - - if (!ret && oact) { - old_ka.sa.sa_flags ^= SUNOS_SV_INTERRUPT; - if (put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) || - __put_user(old_ka.sa.sa_flags, &oact->sa_flags)) - return -EFAULT; - __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask); - } - - return ret; -} - -asmlinkage int sunos_setsockopt(u32 __fd, u32 __level, u32 __optname, - char __user *optval, u32 __optlen) -{ - int fd = (int) __fd; - int level = (int) __level; - int optname = (int) __optname; - int optlen = (int) __optlen; - int tr_opt = optname; - int ret; - - if (level == SOL_IP) { - /* Multicast socketopts (ttl, membership) */ - if (tr_opt >=2 && tr_opt <= 6) - tr_opt += 30; - } - ret = sys_setsockopt(fd, level, tr_opt, - optval, optlen); - return ret; -} - -asmlinkage int sunos_getsockopt(u32 __fd, u32 __level, u32 __optname, - char __user *optval, int __user *optlen) -{ - int fd = (int) __fd; - int level = (int) __level; - int optname = (int) __optname; - int tr_opt = optname; - int ret; - - if (level == SOL_IP) { - /* Multicast socketopts (ttl, membership) */ - if (tr_opt >=2 && tr_opt <= 6) - tr_opt += 30; - } - ret = compat_sys_getsockopt(fd, level, tr_opt, - optval, optlen); - return ret; -} diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 6b9b718e24af..a4fef2ba1ae1 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S @@ -155,125 +155,3 @@ sys_call_table: .word sys_set_mempolicy, sys_kexec_load, sys_move_pages, sys_getcpu, sys_epoll_pwait /*310*/ .word sys_utimensat, sys_signalfd, sys_timerfd_create, sys_eventfd, sys_fallocate .word sys_timerfd_settime, sys_timerfd_gettime - -#if defined(CONFIG_SUNOS_EMUL) || defined(CONFIG_SOLARIS_EMUL) || \ - defined(CONFIG_SOLARIS_EMUL_MODULE) - /* Now the 32-bit SunOS syscall table. */ - - .align 4 - .globl sunos_sys_table -sunos_sys_table: -/*0*/ .word sunos_indir, sys32_exit, sys_fork - .word sunos_read, sunos_write, sunos_open - .word sys_close, sunos_wait4, sys_creat - .word sys_link, sys_unlink, sunos_execv - .word sys_chdir, sunos_nosys, sys32_mknod - .word sys_chmod, sys32_lchown16, sunos_brk - .word sunos_nosys, sys32_lseek, sunos_getpid - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_getuid, sunos_nosys, sys_ptrace - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sys_access, sunos_nosys, sunos_nosys - .word sys_sync, sys_kill, compat_sys_newstat - .word sunos_nosys, compat_sys_newlstat, sys_dup - .word sys_pipe, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_getgid - .word sunos_nosys, sunos_nosys -/*50*/ .word sunos_nosys, sys_acct, sunos_nosys - .word sunos_mctl, sunos_ioctl, sys_reboot - .word sunos_nosys, sys_symlink, sys_readlink - .word sys32_execve, sys_umask, sys_chroot - .word compat_sys_newfstat, sunos_nosys, sys_getpagesize - .word sys_msync, sys_vfork, sunos_nosys - .word sunos_nosys, sunos_sbrk, sunos_sstk - .word sunos_mmap, sunos_vadvise, sys_munmap - .word sys_mprotect, sys_madvise, sys_vhangup - .word sunos_nosys, sys_mincore, sys32_getgroups16 - .word sys32_setgroups16, sys_getpgrp, sunos_setpgrp - .word compat_sys_setitimer, sunos_nosys, sys_swapon - .word compat_sys_getitimer, sys_gethostname, sys_sethostname - .word sunos_getdtablesize, sys_dup2, sunos_nop - .word compat_sys_fcntl, sunos_select, sunos_nop - .word sys_fsync, sys32_setpriority, sys32_socket - .word sys32_connect, sunos_accept -/*100*/ .word sys_getpriority, sunos_send, sunos_recv - .word sunos_nosys, sys32_bind, sunos_setsockopt - .word sys32_listen, sunos_nosys, sunos_sigaction - .word sunos_sigblock, sunos_sigsetmask, sys_sigpause - .word sys32_sigstack, sys32_recvmsg, sys32_sendmsg - .word sunos_nosys, sys32_gettimeofday, compat_sys_getrusage - .word sunos_getsockopt, sunos_nosys, sunos_readv - .word sunos_writev, sys32_settimeofday, sys32_fchown16 - .word sys_fchmod, sys32_recvfrom, sys32_setreuid16 - .word sys32_setregid16, sys_rename, sys_truncate - .word sys_ftruncate, sys_flock, sunos_nosys - .word sys32_sendto, sys32_shutdown, sys32_socketpair - .word sys_mkdir, sys_rmdir, sys32_utimes - .word sys32_sigreturn, sunos_nosys, sys32_getpeername - .word sunos_gethostid, sunos_nosys, compat_sys_getrlimit - .word compat_sys_setrlimit, sunos_killpg, sunos_nosys - .word sunos_nosys, sunos_nosys -/*150*/ .word sys32_getsockname, sunos_nosys, sunos_nosys - .word sys_poll, sunos_nosys, sunos_nosys - .word sunos_getdirentries, compat_sys_statfs, compat_sys_fstatfs - .word sys_oldumount, sunos_nosys, sunos_nosys - .word sys_getdomainname, sys_setdomainname - .word sunos_nosys, sys_quotactl, sunos_nosys - .word sunos_nosys, sys_ustat, sunos_semsys - .word sunos_nosys, sunos_shmsys, sunos_audit - .word sunos_nosys, sunos_getdents, sys_setsid - .word sys_fchdir, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, compat_sys_sigpending, sunos_nosys - .word sys_setpgid, sunos_pathconf, sunos_fpathconf - .word sunos_sysconf, sunos_uname, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys -/*200*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys -/*250*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*260*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*270*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*280*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*290*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*300*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys -/*310*/ .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys, sunos_nosys, sunos_nosys - .word sunos_nosys - -#endif diff --git a/arch/sparc64/kernel/systbls.h b/arch/sparc64/kernel/systbls.h index 8a0d20a35d0c..bc9f5dac4069 100644 --- a/arch/sparc64/kernel/systbls.h +++ b/arch/sparc64/kernel/systbls.h @@ -27,8 +27,6 @@ extern asmlinkage unsigned long sys64_mremap(unsigned long addr, unsigned long new_addr); extern asmlinkage unsigned long c_sys_nis_syscall(struct pt_regs *regs); extern asmlinkage long sys_getdomainname(char __user *name, int len); -extern asmlinkage long solaris_syscall(struct pt_regs *regs); -extern asmlinkage long sunos_syscall(struct pt_regs *regs); extern asmlinkage long sys_utrap_install(utrap_entry_t type, utrap_handler_t new_p, utrap_handler_t new_d, diff --git a/arch/sparc64/kernel/ttable.S b/arch/sparc64/kernel/ttable.S index 7575aa371da8..b0de4c00b11a 100644 --- a/arch/sparc64/kernel/ttable.S +++ b/arch/sparc64/kernel/ttable.S @@ -117,16 +117,13 @@ tl0_f4o: FILL_4_OTHER tl0_f5o: FILL_5_OTHER tl0_f6o: FILL_6_OTHER tl0_f7o: FILL_7_OTHER -tl0_sunos: SUNOS_SYSCALL_TRAP +tl0_resv100: BTRAP(0x100) tl0_bkpt: BREAKPOINT_TRAP tl0_divz: TRAP(do_div0) tl0_flushw: FLUSH_WINDOW_TRAP -tl0_resv104: BTRAP(0x104) BTRAP(0x105) BTRAP(0x106) BTRAP(0x107) - .globl tl0_solaris -tl0_solaris: SOLARIS_SYSCALL_TRAP -tl0_resv109: BTRAP(0x109) -tl0_resv10a: BTRAP(0x10a) BTRAP(0x10b) BTRAP(0x10c) BTRAP(0x10d) BTRAP(0x10e) -tl0_resv10f: BTRAP(0x10f) +tl0_resv104: BTRAP(0x104) BTRAP(0x105) BTRAP(0x106) BTRAP(0x107) BTRAP(0x108) +tl0_resv109: BTRAP(0x109) BTRAP(0x10a) BTRAP(0x10b) BTRAP(0x10c) BTRAP(0x10d) +tl0_resv10e: BTRAP(0x10e) BTRAP(0x10f) tl0_linux32: LINUX_32BIT_SYSCALL_TRAP tl0_oldlinux64: LINUX_64BIT_SYSCALL_TRAP tl0_resv112: TRAP_UTRAP(UT_TRAP_INSTRUCTION_18,0x112) TRAP_UTRAP(UT_TRAP_INSTRUCTION_19,0x113) @@ -139,8 +136,7 @@ tl0_resv11e: TRAP_UTRAP(UT_TRAP_INSTRUCTION_30,0x11e) TRAP_UTRAP(UT_TRAP_INSTRUC tl0_getcc: GETCC_TRAP tl0_setcc: SETCC_TRAP tl0_getpsr: TRAP(do_getpsr) -tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) -tl0_solindir: INDIRECT_SOLARIS_SYSCALL(156) +tl0_resv123: BTRAP(0x123) BTRAP(0x124) BTRAP(0x125) BTRAP(0x126) BTRAP(0x127) tl0_resv128: BTRAP(0x128) BTRAP(0x129) BTRAP(0x12a) BTRAP(0x12b) BTRAP(0x12c) tl0_resv12d: BTRAP(0x12d) BTRAP(0x12e) BTRAP(0x12f) BTRAP(0x130) BTRAP(0x131) tl0_resv132: BTRAP(0x132) BTRAP(0x133) BTRAP(0x134) BTRAP(0x135) BTRAP(0x136) diff --git a/arch/sparc64/solaris/Makefile b/arch/sparc64/solaris/Makefile deleted file mode 100644 index 8c8663033bfb..000000000000 --- a/arch/sparc64/solaris/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# -# Makefile for the Solaris binary emulation. -# - -EXTRA_AFLAGS := -ansi - -solaris-objs := entry64.o fs.o misc.o signal.o systbl.o socket.o \ - ioctl.o ipc.o socksys.o timod.o - -obj-$(CONFIG_SOLARIS_EMUL) += solaris.o diff --git a/arch/sparc64/solaris/conv.h b/arch/sparc64/solaris/conv.h deleted file mode 100644 index 50e58232cf2b..000000000000 --- a/arch/sparc64/solaris/conv.h +++ /dev/null @@ -1,38 +0,0 @@ -/* $Id: conv.h,v 1.4 1998/08/15 20:42:51 davem Exp $ - * conv.h: Utility macros for Solaris emulation - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -/* #define DEBUG_SOLARIS */ -#define DEBUG_SOLARIS_KMALLOC - -#ifndef __ASSEMBLY__ - -#include - -/* Use this to get at 32-bit user passed pointers. */ -#define A(__x) \ -({ unsigned long __ret; \ - __asm__ ("srl %0, 0, %0" \ - : "=r" (__ret) \ - : "0" (__x)); \ - (void __user *)__ret; \ -}) - -extern unsigned sys_call_table[]; -extern unsigned sys_call_table32[]; -extern unsigned sunos_sys_table[]; - -#define SYS(name) ((long)sys_call_table[__NR_##name]) -#define SUNOS(x) ((long)sunos_sys_table[x]) - -#ifdef DEBUG_SOLARIS -#define SOLD(s) printk("%s,%d,%s(): %s\n",__FILE__,__LINE__,__func__,(s)) -#define SOLDD(s) printk("solaris: "); printk s -#else -#define SOLD(s) -#define SOLDD(s) -#endif - -#endif /* __ASSEMBLY__ */ diff --git a/arch/sparc64/solaris/entry64.S b/arch/sparc64/solaris/entry64.S deleted file mode 100644 index f170324e8bf2..000000000000 --- a/arch/sparc64/solaris/entry64.S +++ /dev/null @@ -1,223 +0,0 @@ -/* $Id: entry64.S,v 1.7 2002/02/09 19:49:31 davem Exp $ - * entry64.S: Solaris syscall emulation entry point. - * - * Copyright (C) 1996,1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1995,1997 David S. Miller (davem@caip.rutgers.edu) - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - */ - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "conv.h" - -#define NR_SYSCALLS 256 - - .text -solaris_syscall_trace: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 0, %o1 - srl %i0, 0, %o0 - mov %i4, %o4 - srl %i1, 0, %o1 - mov %i5, %o5 - andcc %l3, 1, %g0 - be,pt %icc, 2f - srl %i2, 0, %o2 - b,pt %xcc, 2f - add %sp, PTREGS_OFF, %o0 - -solaris_sucks: -/* Solaris is a big system which needs to be able to do all the things - * in Inf+1 different ways */ - add %i6, 0x5c, %o0 - mov %i0, %g1 - mov %i1, %i0 - mov %i2, %i1 - srl %o0, 0, %o0 - mov %i3, %i2 - movrz %g1, 256, %g1 /* Ensure we don't loop forever */ - mov %i4, %i3 - mov %i5, %i4 - ba,pt %xcc, solaris_sparc_syscall -exen: lduwa [%o0] ASI_S, %i5 - -exenf: ba,pt %xcc, solaris_sparc_syscall - clr %i5 - -/* For shared binaries, binfmt_elf32 already sets up personality - and exec_domain. This is to handle static binaries as well */ -solaris_reg: - call solaris_register - nop - ba,pt %xcc, 1f - mov %i4, %o4 - -linux_syscall_for_solaris: - sethi %hi(sys_call_table32), %l6 - or %l6, %lo(sys_call_table32), %l6 - sll %l3, 2, %l4 - ba,pt %xcc, 10f - lduw [%l6 + %l4], %l3 - - /* Solaris system calls enter here... */ - .align 32 - .globl solaris_sparc_syscall, entry64_personality_patch -solaris_sparc_syscall: -entry64_personality_patch: - ldub [%g4 + 0x0], %l0 - cmp %g1, 255 - bg,pn %icc, solaris_unimplemented - srl %g1, 0, %g1 - sethi %hi(solaris_sys_table), %l7 - or %l7, %lo(solaris_sys_table), %l7 - brz,pn %g1, solaris_sucks - mov %i4, %o4 - sll %g1, 2, %l4 - cmp %l0, 1 - bne,pn %icc, solaris_reg -1: srl %i0, 0, %o0 - lduw [%l7 + %l4], %l3 - srl %i1, 0, %o1 - ldx [%g6 + TI_FLAGS], %l5 - cmp %l3, NR_SYSCALLS - bleu,a,pn %xcc, linux_syscall_for_solaris - nop - andcc %l3, 1, %g0 - bne,a,pn %icc, 10f - add %sp, PTREGS_OFF, %o0 -10: srl %i2, 0, %o2 - mov %i5, %o5 - andn %l3, 3, %l7 - andcc %l5, _TIF_SYSCALL_TRACE, %g0 - bne,pn %icc, solaris_syscall_trace - mov %i0, %l5 -2: call %l7 - srl %i3, 0, %o3 -ret_from_solaris: - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - ldx [%g6 + TI_FLAGS], %l6 - sra %o0, 0, %o0 - mov %ulo(TSTATE_XCARRY | TSTATE_ICARRY), %g2 - ldx [%sp + PTREGS_OFF + PT_V9_TSTATE], %g3 - cmp %o0, -ERESTART_RESTARTBLOCK - sllx %g2, 32, %g2 - bgeu,pn %xcc, 1f - andcc %l6, _TIF_SYSCALL_TRACE, %l6 - - /* System call success, clear Carry condition code. */ - andn %g3, %g2, %g3 - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, solaris_syscall_trace2 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 - andcc %l1, 1, %g0 - bne,pn %icc, 2f - clr %l6 - add %l1, 0x4, %l2 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ! pc = npc - call rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc+4 - - /* When tnpc & 1, this comes from setcontext and we don't want to advance pc */ -2: andn %l1, 3, %l1 - call rtrap - stx %l1, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc&~3 - -1: - /* System call failure, set Carry condition code. - * Also, get abs(errno) to return to the process. - */ - sub %g0, %o0, %o0 - or %g3, %g2, %g3 - cmp %o0, ERANGE /* 0-ERANGE are identity mapped */ - bleu,pt %icc, 1f - cmp %o0, EMEDIUMTYPE - bgu,pn %icc, 1f - sethi %hi(solaris_err_table), %l6 - sll %o0, 2, %o0 - or %l6, %lo(solaris_err_table), %l6 - ldsw [%l6 + %o0], %o0 -1: stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - mov 1, %l6 - stx %g3, [%sp + PTREGS_OFF + PT_V9_TSTATE] - bne,pn %icc, solaris_syscall_trace2 - ldx [%sp + PTREGS_OFF + PT_V9_TNPC], %l1 - andcc %l1, 1, %g0 - bne,pn %icc, 2b - add %l1, 0x4, %l2 - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] ! pc = npc - call rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] !npc = npc+4 - -solaris_syscall_trace2: - add %sp, PTREGS_OFF, %o0 - call syscall_trace - mov 1, %o1 - add %l1, 0x4, %l2 /* npc = npc+4 */ - andcc %l1, 1, %g0 - bne,pn %icc, 2b - nop - stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] - call rtrap - stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] - - /* This one is tricky, so that's why we do it in assembly */ - .globl solaris_sigsuspend -solaris_sigsuspend: - call do_sol_sigsuspend - nop - brlz,pn %o0, ret_from_solaris - nop - call sys_sigsuspend - stx %o0, [%sp + PTREGS_OFF + PT_V9_I0] - b,pt %xcc, ret_from_solaris - nop - - .globl solaris_getpid -solaris_getpid: - call sys_getppid - nop - call sys_getpid - stx %o0, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_from_solaris - nop - - .globl solaris_getuid -solaris_getuid: - call sys_geteuid - nop - call sys_getuid - stx %o1, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_from_solaris - nop - - .globl solaris_getgid -solaris_getgid: - call sys_getegid - nop - call sys_getgid - stx %o1, [%sp + PTREGS_OFF + PT_V9_I1] - b,pt %xcc, ret_from_solaris - nop - - .globl solaris_unimplemented -solaris_unimplemented: - call do_sol_unimplemented - add %sp, PTREGS_OFF, %o0 - ba,pt %xcc, ret_from_solaris - nop - - .section __ex_table,"a" - .align 4 - .word exen, exenf - diff --git a/arch/sparc64/solaris/fs.c b/arch/sparc64/solaris/fs.c deleted file mode 100644 index 7d035f0d3ae1..000000000000 --- a/arch/sparc64/solaris/fs.c +++ /dev/null @@ -1,745 +0,0 @@ -/* $Id: fs.c,v 1.27 2002/02/08 03:57:14 davem Exp $ - * fs.c: fs related syscall emulation for Solaris - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * - * 1999-08-19 Implemented solaris F_FREESP (truncate) - * fcntl, by Jason Rappleye (rappleye@ccr.buffalo.edu) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "conv.h" - -#define R3_VERSION 1 -#define R4_VERSION 2 - -typedef struct { - s32 tv_sec; - s32 tv_nsec; -} timestruct_t; - -struct sol_stat { - u32 st_dev; - s32 st_pad1[3]; /* network id */ - u32 st_ino; - u32 st_mode; - u32 st_nlink; - u32 st_uid; - u32 st_gid; - u32 st_rdev; - s32 st_pad2[2]; - s32 st_size; - s32 st_pad3; /* st_size, off_t expansion */ - timestruct_t st_atime; - timestruct_t st_mtime; - timestruct_t st_ctime; - s32 st_blksize; - s32 st_blocks; - char st_fstype[16]; - s32 st_pad4[8]; /* expansion area */ -}; - -struct sol_stat64 { - u32 st_dev; - s32 st_pad1[3]; /* network id */ - u64 st_ino; - u32 st_mode; - u32 st_nlink; - u32 st_uid; - u32 st_gid; - u32 st_rdev; - s32 st_pad2[2]; - s64 st_size; - timestruct_t st_atime; - timestruct_t st_mtime; - timestruct_t st_ctime; - s64 st_blksize; - s32 st_blocks; - char st_fstype[16]; - s32 st_pad4[4]; /* expansion area */ -}; - -#define UFSMAGIC (((unsigned)'u'<<24)||((unsigned)'f'<<16)||((unsigned)'s'<<8)) - -static inline int putstat(struct sol_stat __user *ubuf, struct kstat *kbuf) -{ - u32 ino; - - if (kbuf->size > MAX_NON_LFS || - !sysv_valid_dev(kbuf->dev) || - !sysv_valid_dev(kbuf->rdev)) - return -EOVERFLOW; - ino = kbuf->ino; - if (sizeof(ino) < sizeof(kbuf->ino) && ino != kbuf->ino) - return -EOVERFLOW; - if (put_user (sysv_encode_dev(kbuf->dev), &ubuf->st_dev) || - __put_user (ino, &ubuf->st_ino) || - __put_user (kbuf->mode, &ubuf->st_mode) || - __put_user (kbuf->nlink, &ubuf->st_nlink) || - __put_user (kbuf->uid, &ubuf->st_uid) || - __put_user (kbuf->gid, &ubuf->st_gid) || - __put_user (sysv_encode_dev(kbuf->rdev), &ubuf->st_rdev) || - __put_user (kbuf->size, &ubuf->st_size) || - __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec) || - __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec) || - __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec) || - __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec) || - __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec) || - __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec) || - __put_user (kbuf->blksize, &ubuf->st_blksize) || - __put_user (kbuf->blocks, &ubuf->st_blocks) || - __put_user (UFSMAGIC, (unsigned __user *)ubuf->st_fstype)) - return -EFAULT; - return 0; -} - -static inline int putstat64(struct sol_stat64 __user *ubuf, struct kstat *kbuf) -{ - if (!sysv_valid_dev(kbuf->dev) || !sysv_valid_dev(kbuf->rdev)) - return -EOVERFLOW; - if (put_user (sysv_encode_dev(kbuf->dev), &ubuf->st_dev) || - __put_user (kbuf->ino, &ubuf->st_ino) || - __put_user (kbuf->mode, &ubuf->st_mode) || - __put_user (kbuf->nlink, &ubuf->st_nlink) || - __put_user (kbuf->uid, &ubuf->st_uid) || - __put_user (kbuf->gid, &ubuf->st_gid) || - __put_user (sysv_encode_dev(kbuf->rdev), &ubuf->st_rdev) || - __put_user (kbuf->size, &ubuf->st_size) || - __put_user (kbuf->atime.tv_sec, &ubuf->st_atime.tv_sec) || - __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime.tv_nsec) || - __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime.tv_sec) || - __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime.tv_nsec) || - __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime.tv_sec) || - __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime.tv_nsec) || - __put_user (kbuf->blksize, &ubuf->st_blksize) || - __put_user (kbuf->blocks, &ubuf->st_blocks) || - __put_user (UFSMAGIC, (unsigned __user *)ubuf->st_fstype)) - return -EFAULT; - return 0; -} - -asmlinkage int solaris_stat(u32 filename, u32 statbuf) -{ - struct kstat s; - int ret = vfs_stat(A(filename), &s); - if (!ret) - return putstat(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_xstat(int vers, u32 filename, u32 statbuf) -{ - /* Solaris doesn't bother with looking at vers, so we do neither */ - return solaris_stat(filename, statbuf); -} - -asmlinkage int solaris_stat64(u32 filename, u32 statbuf) -{ - struct kstat s; - int ret = vfs_stat(A(filename), &s); - if (!ret) - return putstat64(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_lstat(u32 filename, u32 statbuf) -{ - struct kstat s; - int ret = vfs_lstat(A(filename), &s); - if (!ret) - return putstat(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_lxstat(int vers, u32 filename, u32 statbuf) -{ - return solaris_lstat(filename, statbuf); -} - -asmlinkage int solaris_lstat64(u32 filename, u32 statbuf) -{ - struct kstat s; - int ret = vfs_lstat(A(filename), &s); - if (!ret) - return putstat64(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_fstat(unsigned int fd, u32 statbuf) -{ - struct kstat s; - int ret = vfs_fstat(fd, &s); - if (!ret) - return putstat(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_fxstat(int vers, u32 fd, u32 statbuf) -{ - return solaris_fstat(fd, statbuf); -} - -asmlinkage int solaris_fstat64(unsigned int fd, u32 statbuf) -{ - struct kstat s; - int ret = vfs_fstat(fd, &s); - if (!ret) - return putstat64(A(statbuf), &s); - return ret; -} - -asmlinkage int solaris_mknod(u32 path, u32 mode, s32 dev) -{ - int (*sys_mknod)(const char __user *,int,unsigned) = - (int (*)(const char __user *,int,unsigned))SYS(mknod); - int major = sysv_major(dev); - int minor = sysv_minor(dev); - - /* minor is guaranteed to be OK for MKDEV, major might be not */ - if (major > 0xfff) - return -EINVAL; - return sys_mknod(A(path), mode, new_encode_dev(MKDEV(major,minor))); -} - -asmlinkage int solaris_xmknod(int vers, u32 path, u32 mode, s32 dev) -{ - return solaris_mknod(path, mode, dev); -} - -asmlinkage int solaris_getdents64(unsigned int fd, void __user *dirent, unsigned int count) -{ - int (*sys_getdents)(unsigned int, void __user *, unsigned int) = - (int (*)(unsigned int, void __user *, unsigned int))SYS(getdents); - - return sys_getdents(fd, dirent, count); -} - -/* This statfs thingie probably will go in the near future, but... */ - -struct sol_statfs { - short f_type; - s32 f_bsize; - s32 f_frsize; - s32 f_blocks; - s32 f_bfree; - u32 f_files; - u32 f_ffree; - char f_fname[6]; - char f_fpack[6]; -}; - -asmlinkage int solaris_statfs(u32 path, u32 buf, int len, int fstype) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - int (*sys_statfs)(const char __user *,struct statfs __user *) = - (int (*)(const char __user *,struct statfs __user *))SYS(statfs); - struct sol_statfs __user *ss = A(buf); - - if (len != sizeof(struct sol_statfs)) return -EINVAL; - if (!fstype) { - /* FIXME: mixing userland and kernel pointers */ - set_fs (KERNEL_DS); - ret = sys_statfs(A(path), &s); - set_fs (old_fs); - if (!ret) { - if (put_user (s.f_type, &ss->f_type) || - __put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __clear_user (&ss->f_fname, 12)) - return -EFAULT; - } - return ret; - } -/* Linux can't stat unmounted filesystems so we - * simply lie and claim 100MB of 1GB is free. Sorry. - */ - if (put_user (fstype, &ss->f_type) || - __put_user (1024, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (1024*1024, &ss->f_blocks) || - __put_user (100*1024, &ss->f_bfree) || - __put_user (60000, &ss->f_files) || - __put_user (50000, &ss->f_ffree) || - __clear_user (&ss->f_fname, 12)) - return -EFAULT; - return 0; -} - -asmlinkage int solaris_fstatfs(u32 fd, u32 buf, int len, int fstype) -{ - int ret; - struct statfs s; - mm_segment_t old_fs = get_fs(); - int (*sys_fstatfs)(unsigned,struct statfs __user *) = - (int (*)(unsigned,struct statfs __user *))SYS(fstatfs); - struct sol_statfs __user *ss = A(buf); - - if (len != sizeof(struct sol_statfs)) return -EINVAL; - if (!fstype) { - set_fs (KERNEL_DS); - ret = sys_fstatfs(fd, &s); - set_fs (old_fs); - if (!ret) { - if (put_user (s.f_type, &ss->f_type) || - __put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __clear_user (&ss->f_fname, 12)) - return -EFAULT; - } - return ret; - } - /* Otherwise fstatfs is the same as statfs */ - return solaris_statfs(0, buf, len, fstype); -} - -struct sol_statvfs { - u32 f_bsize; - u32 f_frsize; - u32 f_blocks; - u32 f_bfree; - u32 f_bavail; - u32 f_files; - u32 f_ffree; - u32 f_favail; - u32 f_fsid; - char f_basetype[16]; - u32 f_flag; - u32 f_namemax; - char f_fstr[32]; - u32 f_filler[16]; -}; - -struct sol_statvfs64 { - u32 f_bsize; - u32 f_frsize; - u64 f_blocks; - u64 f_bfree; - u64 f_bavail; - u64 f_files; - u64 f_ffree; - u64 f_favail; - u32 f_fsid; - char f_basetype[16]; - u32 f_flag; - u32 f_namemax; - char f_fstr[32]; - u32 f_filler[16]; -}; - -static int report_statvfs(struct vfsmount *mnt, struct inode *inode, u32 buf) -{ - struct kstatfs s; - int error; - struct sol_statvfs __user *ss = A(buf); - - error = vfs_statfs(mnt->mnt_root, &s); - if (!error) { - const char *p = mnt->mnt_sb->s_type->name; - int i = 0; - int j = strlen (p); - - if (j > 15) j = 15; - if (IS_RDONLY(inode)) i = 1; - if (mnt->mnt_flags & MNT_NOSUID) i |= 2; - if (!sysv_valid_dev(inode->i_sb->s_dev)) - return -EOVERFLOW; - if (put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_bavail, &ss->f_bavail) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __put_user (s.f_ffree, &ss->f_favail) || - __put_user (sysv_encode_dev(inode->i_sb->s_dev), &ss->f_fsid) || - __copy_to_user (ss->f_basetype,p,j) || - __put_user (0, (char __user *)&ss->f_basetype[j]) || - __put_user (s.f_namelen, &ss->f_namemax) || - __put_user (i, &ss->f_flag) || - __clear_user (&ss->f_fstr, 32)) - return -EFAULT; - } - return error; -} - -static int report_statvfs64(struct vfsmount *mnt, struct inode *inode, u32 buf) -{ - struct kstatfs s; - int error; - struct sol_statvfs64 __user *ss = A(buf); - - error = vfs_statfs(mnt->mnt_root, &s); - if (!error) { - const char *p = mnt->mnt_sb->s_type->name; - int i = 0; - int j = strlen (p); - - if (j > 15) j = 15; - if (IS_RDONLY(inode)) i = 1; - if (mnt->mnt_flags & MNT_NOSUID) i |= 2; - if (!sysv_valid_dev(inode->i_sb->s_dev)) - return -EOVERFLOW; - if (put_user (s.f_bsize, &ss->f_bsize) || - __put_user (0, &ss->f_frsize) || - __put_user (s.f_blocks, &ss->f_blocks) || - __put_user (s.f_bfree, &ss->f_bfree) || - __put_user (s.f_bavail, &ss->f_bavail) || - __put_user (s.f_files, &ss->f_files) || - __put_user (s.f_ffree, &ss->f_ffree) || - __put_user (s.f_ffree, &ss->f_favail) || - __put_user (sysv_encode_dev(inode->i_sb->s_dev), &ss->f_fsid) || - __copy_to_user (ss->f_basetype,p,j) || - __put_user (0, (char __user *)&ss->f_basetype[j]) || - __put_user (s.f_namelen, &ss->f_namemax) || - __put_user (i, &ss->f_flag) || - __clear_user (&ss->f_fstr, 32)) - return -EFAULT; - } - return error; -} - -asmlinkage int solaris_statvfs(u32 path, u32 buf) -{ - struct nameidata nd; - int error; - - error = user_path_walk(A(path),&nd); - if (!error) { - struct inode *inode = nd.path.dentry->d_inode; - error = report_statvfs(nd.path.mnt, inode, buf); - path_put(&nd.path); - } - return error; -} - -asmlinkage int solaris_fstatvfs(unsigned int fd, u32 buf) -{ - struct file * file; - int error; - - error = -EBADF; - file = fget(fd); - if (file) { - error = report_statvfs(file->f_path.mnt, file->f_path.dentry->d_inode, buf); - fput(file); - } - - return error; -} - -asmlinkage int solaris_statvfs64(u32 path, u32 buf) -{ - struct nameidata nd; - int error; - - lock_kernel(); - error = user_path_walk(A(path), &nd); - if (!error) { - struct inode *inode = nd.path.dentry->d_inode; - error = report_statvfs64(nd.path.mnt, inode, buf); - path_put(&nd.path); - } - unlock_kernel(); - return error; -} - -asmlinkage int solaris_fstatvfs64(unsigned int fd, u32 buf) -{ - struct file * file; - int error; - - error = -EBADF; - file = fget(fd); - if (file) { - lock_kernel(); - error = report_statvfs64(file->f_path.mnt, file->f_path.dentry->d_inode, buf); - unlock_kernel(); - fput(file); - } - return error; -} - -extern asmlinkage long sparc32_open(const char * filename, int flags, int mode); - -asmlinkage int solaris_open(u32 fname, int flags, u32 mode) -{ - const char *filename = (const char *)(long)fname; - int fl = flags & 0xf; - - /* Translate flags first. */ - if (flags & 0x2000) fl |= O_LARGEFILE; - if (flags & 0x8050) fl |= O_SYNC; - if (flags & 0x80) fl |= O_NONBLOCK; - if (flags & 0x100) fl |= O_CREAT; - if (flags & 0x200) fl |= O_TRUNC; - if (flags & 0x400) fl |= O_EXCL; - if (flags & 0x800) fl |= O_NOCTTY; - flags = fl; - - return sparc32_open(filename, flags, mode); -} - -#define SOL_F_SETLK 6 -#define SOL_F_SETLKW 7 -#define SOL_F_FREESP 11 -#define SOL_F_ISSTREAM 13 -#define SOL_F_GETLK 14 -#define SOL_F_PRIV 15 -#define SOL_F_NPRIV 16 -#define SOL_F_QUOTACTL 17 -#define SOL_F_BLOCKS 18 -#define SOL_F_BLKSIZE 19 -#define SOL_F_GETOWN 23 -#define SOL_F_SETOWN 24 - -struct sol_flock { - short l_type; - short l_whence; - u32 l_start; - u32 l_len; - s32 l_sysid; - s32 l_pid; - s32 l_pad[4]; -}; - -asmlinkage int solaris_fcntl(unsigned fd, unsigned cmd, u32 arg) -{ - int (*sys_fcntl)(unsigned,unsigned,unsigned long) = - (int (*)(unsigned,unsigned,unsigned long))SYS(fcntl); - int ret, flags; - - switch (cmd) { - case F_DUPFD: - case F_GETFD: - case F_SETFD: return sys_fcntl(fd, cmd, (unsigned long)arg); - case F_GETFL: - flags = sys_fcntl(fd, cmd, 0); - ret = flags & 0xf; - if (flags & O_SYNC) ret |= 0x8050; - if (flags & O_NONBLOCK) ret |= 0x80; - return ret; - case F_SETFL: - flags = arg & 0xf; - if (arg & 0x8050) flags |= O_SYNC; - if (arg & 0x80) flags |= O_NONBLOCK; - return sys_fcntl(fd, cmd, (long)flags); - case SOL_F_GETLK: - case SOL_F_SETLK: - case SOL_F_SETLKW: - { - struct flock f; - struct sol_flock __user *p = A(arg); - mm_segment_t old_fs = get_fs(); - - switch (cmd) { - case SOL_F_GETLK: cmd = F_GETLK; break; - case SOL_F_SETLK: cmd = F_SETLK; break; - case SOL_F_SETLKW: cmd = F_SETLKW; break; - } - - if (get_user (f.l_type, &p->l_type) || - __get_user (f.l_whence, &p->l_whence) || - __get_user (f.l_start, &p->l_start) || - __get_user (f.l_len, &p->l_len) || - __get_user (f.l_pid, &p->l_sysid)) - return -EFAULT; - - set_fs(KERNEL_DS); - ret = sys_fcntl(fd, cmd, (unsigned long)&f); - set_fs(old_fs); - - if (__put_user (f.l_type, &p->l_type) || - __put_user (f.l_whence, &p->l_whence) || - __put_user (f.l_start, &p->l_start) || - __put_user (f.l_len, &p->l_len) || - __put_user (f.l_pid, &p->l_pid) || - __put_user (0, &p->l_sysid)) - return -EFAULT; - - return ret; - } - case SOL_F_FREESP: - { - int length; - int (*sys_newftruncate)(unsigned int, unsigned long)= - (int (*)(unsigned int, unsigned long))SYS(ftruncate); - - if (get_user(length, &((struct sol_flock __user *)A(arg))->l_start)) - return -EFAULT; - - return sys_newftruncate(fd, length); - } - }; - return -EINVAL; -} - -asmlinkage int solaris_ulimit(int cmd, int val) -{ - switch (cmd) { - case 1: /* UL_GETFSIZE - in 512B chunks */ - return current->signal->rlim[RLIMIT_FSIZE].rlim_cur >> 9; - case 2: /* UL_SETFSIZE */ - if ((unsigned long)val > (LONG_MAX>>9)) return -ERANGE; - val <<= 9; - task_lock(current->group_leader); - if (val > current->signal->rlim[RLIMIT_FSIZE].rlim_max) { - if (!capable(CAP_SYS_RESOURCE)) { - task_unlock(current->group_leader); - return -EPERM; - } - current->signal->rlim[RLIMIT_FSIZE].rlim_max = val; - } - current->signal->rlim[RLIMIT_FSIZE].rlim_cur = val; - task_unlock(current->group_leader); - return 0; - case 3: /* UL_GMEMLIM */ - return current->signal->rlim[RLIMIT_DATA].rlim_cur; - case 4: /* UL_GDESLIM */ - return sysctl_nr_open; - } - return -EINVAL; -} - -/* At least at the time I'm writing this, Linux doesn't have ACLs, so we - just fake this */ -asmlinkage int solaris_acl(u32 filename, int cmd, int nentries, u32 aclbufp) -{ - return -ENOSYS; -} - -asmlinkage int solaris_facl(unsigned int fd, int cmd, int nentries, u32 aclbufp) -{ - return -ENOSYS; -} - -asmlinkage int solaris_pread(unsigned int fd, char __user *buf, u32 count, u32 pos) -{ - ssize_t (*sys_pread64)(unsigned int, char __user *, size_t, loff_t) = - (ssize_t (*)(unsigned int, char __user *, size_t, loff_t))SYS(pread64); - - return sys_pread64(fd, buf, count, (loff_t)pos); -} - -asmlinkage int solaris_pwrite(unsigned int fd, char __user *buf, u32 count, u32 pos) -{ - ssize_t (*sys_pwrite64)(unsigned int, char __user *, size_t, loff_t) = - (ssize_t (*)(unsigned int, char __user *, size_t, loff_t))SYS(pwrite64); - - return sys_pwrite64(fd, buf, count, (loff_t)pos); -} - -/* POSIX.1 names */ -#define _PC_LINK_MAX 1 -#define _PC_MAX_CANON 2 -#define _PC_MAX_INPUT 3 -#define _PC_NAME_MAX 4 -#define _PC_PATH_MAX 5 -#define _PC_PIPE_BUF 6 -#define _PC_NO_TRUNC 7 -#define _PC_VDISABLE 8 -#define _PC_CHOWN_RESTRICTED 9 -/* POSIX.4 names */ -#define _PC_ASYNC_IO 10 -#define _PC_PRIO_IO 11 -#define _PC_SYNC_IO 12 -#define _PC_LAST 12 - -/* This is not a real and complete implementation yet, just to keep - * the easy Solaris binaries happy. - */ -asmlinkage int solaris_fpathconf(int fd, int name) -{ - int ret; - - switch(name) { - case _PC_LINK_MAX: - ret = LINK_MAX; - break; - case _PC_MAX_CANON: - ret = MAX_CANON; - break; - case _PC_MAX_INPUT: - ret = MAX_INPUT; - break; - case _PC_NAME_MAX: - ret = NAME_MAX; - break; - case _PC_PATH_MAX: - ret = PATH_MAX; - break; - case _PC_PIPE_BUF: - ret = PIPE_BUF; - break; - case _PC_CHOWN_RESTRICTED: - ret = 1; - break; - case _PC_NO_TRUNC: - case _PC_VDISABLE: - ret = 0; - break; - default: - ret = -EINVAL; - break; - } - return ret; -} - -asmlinkage int solaris_pathconf(u32 path, int name) -{ - return solaris_fpathconf(0, name); -} - -/* solaris_llseek returns long long - quite difficult */ -asmlinkage long solaris_llseek(struct pt_regs *regs, u32 off_hi, u32 off_lo, int whence) -{ - int (*sys_llseek)(unsigned int, unsigned long, unsigned long, loff_t __user *, unsigned int) = - (int (*)(unsigned int, unsigned long, unsigned long, loff_t __user *, unsigned int))SYS(_llseek); - int ret; - mm_segment_t old_fs = get_fs(); - loff_t retval; - - set_fs(KERNEL_DS); - ret = sys_llseek((unsigned int)regs->u_regs[UREG_I0], off_hi, off_lo, &retval, whence); - set_fs(old_fs); - if (ret < 0) return ret; - regs->u_regs[UREG_I1] = (u32)retval; - return (retval >> 32); -} - -/* Have to mask out all but lower 3 bits */ -asmlinkage int solaris_access(u32 filename, long mode) -{ - int (*sys_access)(const char __user *, int) = - (int (*)(const char __user *, int))SYS(access); - - return sys_access(A(filename), mode & 7); -} diff --git a/arch/sparc64/solaris/ioctl.c b/arch/sparc64/solaris/ioctl.c deleted file mode 100644 index 8ad10a6d993b..000000000000 --- a/arch/sparc64/solaris/ioctl.c +++ /dev/null @@ -1,825 +0,0 @@ -/* $Id: ioctl.c,v 1.17 2002/02/08 03:57:14 davem Exp $ - * ioctl.c: Solaris ioctl emulation. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997,1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) - * - * Streams & timod emulation based on code - * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) - * - * 1999-08-19 Implemented solaris 'm' (mag tape) and - * 'O' (openprom) ioctls, by Jason Rappleye - * (rappleye@ccr.buffalo.edu) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include -#include - -#include "conv.h" -#include "socksys.h" - -extern asmlinkage int compat_sys_ioctl(unsigned int fd, unsigned int cmd, - u32 arg); -asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg); - -extern int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len, - char __user *data_buf, int data_len, int flags); -extern int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, int __user *ctl_len, - char __user *data_buf, int data_maxlen, int __user *data_len, int *flags); - -/* termio* stuff {{{ */ - -struct solaris_termios { - u32 c_iflag; - u32 c_oflag; - u32 c_cflag; - u32 c_lflag; - u8 c_cc[19]; -}; - -struct solaris_termio { - u16 c_iflag; - u16 c_oflag; - u16 c_cflag; - u16 c_lflag; - s8 c_line; - u8 c_cc[8]; -}; - -struct solaris_termiox { - u16 x_hflag; - u16 x_cflag; - u16 x_rflag[5]; - u16 x_sflag; -}; - -static u32 solaris_to_linux_cflag(u32 cflag) -{ - cflag &= 0x7fdff000; - if (cflag & 0x200000) { - int baud = cflag & 0xf; - cflag &= ~0x20000f; - switch (baud) { - case 0: baud = B57600; break; - case 1: baud = B76800; break; - case 2: baud = B115200; break; - case 3: baud = B153600; break; - case 4: baud = B230400; break; - case 5: baud = B307200; break; - case 6: baud = B460800; break; - } - cflag |= CBAUDEX | baud; - } - return cflag; -} - -static u32 linux_to_solaris_cflag(u32 cflag) -{ - cflag &= ~(CMSPAR | CIBAUD); - if (cflag & CBAUDEX) { - int baud = cflag & CBAUD; - cflag &= ~CBAUD; - switch (baud) { - case B57600: baud = 0; break; - case B76800: baud = 1; break; - case B115200: baud = 2; break; - case B153600: baud = 3; break; - case B230400: baud = 4; break; - case B307200: baud = 5; break; - case B460800: baud = 6; break; - case B614400: baud = 7; break; - case B921600: baud = 8; break; -#if 0 - case B1843200: baud = 9; break; -#endif - } - cflag |= 0x200000 | baud; - } - return cflag; -} - -static inline int linux_to_solaris_termio(unsigned int fd, unsigned int cmd, u32 arg) -{ - struct solaris_termio __user *p = A(arg); - int ret; - - ret = sys_ioctl(fd, cmd, (unsigned long)p); - if (!ret) { - u32 cflag; - - if (__get_user (cflag, &p->c_cflag)) - return -EFAULT; - cflag = linux_to_solaris_cflag(cflag); - if (__put_user (cflag, &p->c_cflag)) - return -EFAULT; - } - return ret; -} - -static int solaris_to_linux_termio(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret; - struct solaris_termio s; - mm_segment_t old_fs = get_fs(); - - if (copy_from_user (&s, (struct solaris_termio __user *)A(arg), sizeof(struct solaris_termio))) - return -EFAULT; - s.c_cflag = solaris_to_linux_cflag(s.c_cflag); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long)&s); - set_fs(old_fs); - return ret; -} - -static inline int linux_to_solaris_termios(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret; - struct solaris_termios s; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long)&s); - set_fs(old_fs); - if (!ret) { - struct solaris_termios __user *p = A(arg); - if (put_user (s.c_iflag, &p->c_iflag) || - __put_user (s.c_oflag, &p->c_oflag) || - __put_user (linux_to_solaris_cflag(s.c_cflag), &p->c_cflag) || - __put_user (s.c_lflag, &p->c_lflag) || - __copy_to_user (p->c_cc, s.c_cc, 16) || - __clear_user (p->c_cc + 16, 2)) - return -EFAULT; - } - return ret; -} - -static int solaris_to_linux_termios(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret; - struct solaris_termios s; - struct solaris_termios __user *p = A(arg); - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, TCGETS, (unsigned long)&s); - set_fs(old_fs); - if (ret) return ret; - if (put_user (s.c_iflag, &p->c_iflag) || - __put_user (s.c_oflag, &p->c_oflag) || - __put_user (s.c_cflag, &p->c_cflag) || - __put_user (s.c_lflag, &p->c_lflag) || - __copy_from_user (s.c_cc, p->c_cc, 16)) - return -EFAULT; - s.c_cflag = solaris_to_linux_cflag(s.c_cflag); - set_fs(KERNEL_DS); - ret = sys_ioctl(fd, cmd, (unsigned long)&s); - set_fs(old_fs); - return ret; -} - -static inline int solaris_T(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 1: /* TCGETA */ - return linux_to_solaris_termio(fd, TCGETA, arg); - case 2: /* TCSETA */ - return solaris_to_linux_termio(fd, TCSETA, arg); - case 3: /* TCSETAW */ - return solaris_to_linux_termio(fd, TCSETAW, arg); - case 4: /* TCSETAF */ - return solaris_to_linux_termio(fd, TCSETAF, arg); - case 5: /* TCSBRK */ - return sys_ioctl(fd, TCSBRK, arg); - case 6: /* TCXONC */ - return sys_ioctl(fd, TCXONC, arg); - case 7: /* TCFLSH */ - return sys_ioctl(fd, TCFLSH, arg); - case 13: /* TCGETS */ - return linux_to_solaris_termios(fd, TCGETS, arg); - case 14: /* TCSETS */ - return solaris_to_linux_termios(fd, TCSETS, arg); - case 15: /* TCSETSW */ - return solaris_to_linux_termios(fd, TCSETSW, arg); - case 16: /* TCSETSF */ - return solaris_to_linux_termios(fd, TCSETSF, arg); - case 103: /* TIOCSWINSZ */ - return sys_ioctl(fd, TIOCSWINSZ, arg); - case 104: /* TIOCGWINSZ */ - return sys_ioctl(fd, TIOCGWINSZ, arg); - } - return -ENOSYS; -} - -static inline int solaris_t(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 20: /* TIOCGPGRP */ - return sys_ioctl(fd, TIOCGPGRP, arg); - case 21: /* TIOCSPGRP */ - return sys_ioctl(fd, TIOCSPGRP, arg); - } - return -ENOSYS; -} - -/* }}} */ - -/* A pseudo STREAMS support {{{ */ - -struct strioctl { - int cmd, timeout, len; - u32 data; -}; - -struct solaris_si_sockparams { - int sp_family; - int sp_type; - int sp_protocol; -}; - -struct solaris_o_si_udata { - int tidusize; - int addrsize; - int optsize; - int etsdusize; - int servtype; - int so_state; - int so_options; - int tsdusize; -}; - -struct solaris_si_udata { - int tidusize; - int addrsize; - int optsize; - int etsdusize; - int servtype; - int so_state; - int so_options; - int tsdusize; - struct solaris_si_sockparams sockparams; -}; - -#define SOLARIS_MODULE_TIMOD 0 -#define SOLARIS_MODULE_SOCKMOD 1 -#define SOLARIS_MODULE_MAX 2 - -static struct module_info { - const char *name; - /* can be expanded further if needed */ -} module_table[ SOLARIS_MODULE_MAX + 1 ] = { - /* the ordering here must match the module numbers above! */ - { "timod" }, - { "sockmod" }, - { NULL } -}; - -static inline int solaris_sockmod(unsigned int fd, unsigned int cmd, u32 arg) -{ - struct inode *ino; - struct fdtable *fdt; - /* I wonder which of these tests are superfluous... --patrik */ - rcu_read_lock(); - fdt = files_fdtable(current->files); - if (! fdt->fd[fd] || - ! fdt->fd[fd]->f_path.dentry || - ! (ino = fdt->fd[fd]->f_path.dentry->d_inode) || - ! S_ISSOCK(ino->i_mode)) { - rcu_read_unlock(); - return TBADF; - } - rcu_read_unlock(); - - switch (cmd & 0xff) { - case 109: /* SI_SOCKPARAMS */ - { - struct solaris_si_sockparams si; - if (copy_from_user (&si, A(arg), sizeof(si))) - return (EFAULT << 8) | TSYSERR; - - /* Should we modify socket ino->socket_i.ops and type? */ - return 0; - } - case 110: /* SI_GETUDATA */ - { - int etsdusize, servtype; - struct solaris_si_udata __user *p = A(arg); - switch (SOCKET_I(ino)->type) { - case SOCK_STREAM: - etsdusize = 1; - servtype = 2; - break; - default: - etsdusize = -2; - servtype = 3; - break; - } - if (put_user(16384, &p->tidusize) || - __put_user(sizeof(struct sockaddr), &p->addrsize) || - __put_user(-1, &p->optsize) || - __put_user(etsdusize, &p->etsdusize) || - __put_user(servtype, &p->servtype) || - __put_user(0, &p->so_state) || - __put_user(0, &p->so_options) || - __put_user(16384, &p->tsdusize) || - __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_family) || - __put_user(SOCKET_I(ino)->type, &p->sockparams.sp_type) || - __put_user(SOCKET_I(ino)->ops->family, &p->sockparams.sp_protocol)) - return (EFAULT << 8) | TSYSERR; - return 0; - } - case 101: /* O_SI_GETUDATA */ - { - int etsdusize, servtype; - struct solaris_o_si_udata __user *p = A(arg); - switch (SOCKET_I(ino)->type) { - case SOCK_STREAM: - etsdusize = 1; - servtype = 2; - break; - default: - etsdusize = -2; - servtype = 3; - break; - } - if (put_user(16384, &p->tidusize) || - __put_user(sizeof(struct sockaddr), &p->addrsize) || - __put_user(-1, &p->optsize) || - __put_user(etsdusize, &p->etsdusize) || - __put_user(servtype, &p->servtype) || - __put_user(0, &p->so_state) || - __put_user(0, &p->so_options) || - __put_user(16384, &p->tsdusize)) - return (EFAULT << 8) | TSYSERR; - return 0; - } - case 102: /* SI_SHUTDOWN */ - case 103: /* SI_LISTEN */ - case 104: /* SI_SETMYNAME */ - case 105: /* SI_SETPEERNAME */ - case 106: /* SI_GETINTRANSIT */ - case 107: /* SI_TCL_LINK */ - case 108: /* SI_TCL_UNLINK */ - ; - } - return TNOTSUPPORT; -} - -static inline int solaris_timod(unsigned int fd, unsigned int cmd, u32 arg, - int len, int __user *len_p) -{ - int ret; - - switch (cmd & 0xff) { - case 141: /* TI_OPTMGMT */ - { - int i; - u32 prim; - SOLD("TI_OPMGMT entry"); - ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0); - SOLD("timod_putmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - i = MSG_HIPRI; - SOLD("calling timod_getmsg()"); - ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i); - SOLD("timod_getmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - SOLD("ret ok"); - if (get_user(prim, (u32 __user *)A(arg))) - return (EFAULT << 8) | TSYSERR; - SOLD("got prim"); - if (prim == T_ERROR_ACK) { - u32 tmp, tmp2; - SOLD("prim is T_ERROR_ACK"); - if (get_user(tmp, (u32 __user *)A(arg)+3) || - get_user(tmp2, (u32 __user *)A(arg)+2)) - return (EFAULT << 8) | TSYSERR; - return (tmp2 << 8) | tmp; - } - SOLD("TI_OPMGMT return 0"); - return 0; - } - case 142: /* TI_BIND */ - { - int i; - u32 prim; - SOLD("TI_BIND entry"); - ret = timod_putmsg(fd, A(arg), len, NULL, -1, 0); - SOLD("timod_putmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - len = 1024; /* Solaris allows arbitrary return size */ - i = MSG_HIPRI; - SOLD("calling timod_getmsg()"); - ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i); - SOLD("timod_getmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - SOLD("ret ok"); - if (get_user(prim, (u32 __user *)A(arg))) - return (EFAULT << 8) | TSYSERR; - SOLD("got prim"); - if (prim == T_ERROR_ACK) { - u32 tmp, tmp2; - SOLD("prim is T_ERROR_ACK"); - if (get_user(tmp, (u32 __user *)A(arg)+3) || - get_user(tmp2, (u32 __user *)A(arg)+2)) - return (EFAULT << 8) | TSYSERR; - return (tmp2 << 8) | tmp; - } - SOLD("no ERROR_ACK requested"); - if (prim != T_OK_ACK) - return TBADSEQ; - SOLD("OK_ACK requested"); - i = MSG_HIPRI; - SOLD("calling timod_getmsg()"); - ret = timod_getmsg(fd, A(arg), len, len_p, NULL, -1, NULL, &i); - SOLD("timod_getmsg() returned"); - if (ret) - return (-ret << 8) | TSYSERR; - SOLD("TI_BIND return ok"); - return 0; - } - case 140: /* TI_GETINFO */ - case 143: /* TI_UNBIND */ - case 144: /* TI_GETMYNAME */ - case 145: /* TI_GETPEERNAME */ - case 146: /* TI_SETMYNAME */ - case 147: /* TI_SETPEERNAME */ - ; - } - return TNOTSUPPORT; -} - -static inline int solaris_S(struct file *filp, unsigned int fd, unsigned int cmd, u32 arg) -{ - char *p; - int ret; - mm_segment_t old_fs; - struct strioctl si; - struct inode *ino; - struct sol_socket_struct *sock; - struct module_info *mi; - - ino = filp->f_path.dentry->d_inode; - if (!S_ISSOCK(ino->i_mode)) - return -EBADF; - sock = filp->private_data; - if (! sock) { - printk("solaris_S: NULL private_data\n"); - return -EBADF; - } - if (sock->magic != SOLARIS_SOCKET_MAGIC) { - printk("solaris_S: invalid magic\n"); - return -EBADF; - } - - - switch (cmd & 0xff) { - case 1: /* I_NREAD */ - return -ENOSYS; - case 2: /* I_PUSH */ - { - p = getname (A(arg)); - if (IS_ERR (p)) - return PTR_ERR(p); - ret = -EINVAL; - for (mi = module_table; mi->name; mi++) { - if (strcmp(mi->name, p) == 0) { - sol_module m; - if (sock->modcount >= MAX_NR_STREAM_MODULES) { - ret = -ENXIO; - break; - } - m = (sol_module) (mi - module_table); - sock->module[sock->modcount++] = m; - ret = 0; - break; - } - } - putname (p); - return ret; - } - case 3: /* I_POP */ - if (sock->modcount <= 0) return -EINVAL; - sock->modcount--; - return 0; - case 4: /* I_LOOK */ - { - const char *p; - if (sock->modcount <= 0) return -EINVAL; - p = module_table[(unsigned)sock->module[sock->modcount]].name; - if (copy_to_user (A(arg), p, strlen(p))) - return -EFAULT; - return 0; - } - case 5: /* I_FLUSH */ - return 0; - case 8: /* I_STR */ - if (copy_from_user(&si, A(arg), sizeof(struct strioctl))) - return -EFAULT; - /* We ignore what module is actually at the top of stack. */ - switch ((si.cmd >> 8) & 0xff) { - case 'I': - return solaris_sockmod(fd, si.cmd, si.data); - case 'T': - return solaris_timod(fd, si.cmd, si.data, si.len, - &((struct strioctl __user *)A(arg))->len); - default: - return solaris_ioctl(fd, si.cmd, si.data); - } - case 9: /* I_SETSIG */ - return sys_ioctl(fd, FIOSETOWN, current->pid); - case 10: /* I_GETSIG */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - sys_ioctl(fd, FIOGETOWN, (unsigned long)&ret); - set_fs(old_fs); - if (ret == current->pid) return 0x3ff; - else return -EINVAL; - case 11: /* I_FIND */ - { - int i; - p = getname (A(arg)); - if (IS_ERR (p)) - return PTR_ERR(p); - ret = 0; - for (i = 0; i < sock->modcount; i++) { - unsigned m = sock->module[i]; - if (strcmp(module_table[m].name, p) == 0) { - ret = 1; - break; - } - } - putname (p); - return ret; - } - case 19: /* I_SWROPT */ - case 32: /* I_SETCLTIME */ - return 0; /* Lie */ - } - return -ENOSYS; -} - -static inline int solaris_s(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 0: /* SIOCSHIWAT */ - case 2: /* SIOCSLOWAT */ - return 0; /* We don't support them */ - case 1: /* SIOCGHIWAT */ - case 3: /* SIOCGLOWAT */ - if (put_user (0, (u32 __user *)A(arg))) - return -EFAULT; - return 0; /* Lie */ - case 7: /* SIOCATMARK */ - return sys_ioctl(fd, SIOCATMARK, arg); - case 8: /* SIOCSPGRP */ - return sys_ioctl(fd, SIOCSPGRP, arg); - case 9: /* SIOCGPGRP */ - return sys_ioctl(fd, SIOCGPGRP, arg); - } - return -ENOSYS; -} - -static inline int solaris_r(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 10: /* SIOCADDRT */ - return compat_sys_ioctl(fd, SIOCADDRT, arg); - case 11: /* SIOCDELRT */ - return compat_sys_ioctl(fd, SIOCDELRT, arg); - } - return -ENOSYS; -} - -static inline int solaris_i(unsigned int fd, unsigned int cmd, u32 arg) -{ - switch (cmd & 0xff) { - case 12: /* SIOCSIFADDR */ - return compat_sys_ioctl(fd, SIOCSIFADDR, arg); - case 13: /* SIOCGIFADDR */ - return compat_sys_ioctl(fd, SIOCGIFADDR, arg); - case 14: /* SIOCSIFDSTADDR */ - return compat_sys_ioctl(fd, SIOCSIFDSTADDR, arg); - case 15: /* SIOCGIFDSTADDR */ - return compat_sys_ioctl(fd, SIOCGIFDSTADDR, arg); - case 16: /* SIOCSIFFLAGS */ - return compat_sys_ioctl(fd, SIOCSIFFLAGS, arg); - case 17: /* SIOCGIFFLAGS */ - return compat_sys_ioctl(fd, SIOCGIFFLAGS, arg); - case 18: /* SIOCSIFMEM */ - return compat_sys_ioctl(fd, SIOCSIFMEM, arg); - case 19: /* SIOCGIFMEM */ - return compat_sys_ioctl(fd, SIOCGIFMEM, arg); - case 20: /* SIOCGIFCONF */ - return compat_sys_ioctl(fd, SIOCGIFCONF, arg); - case 21: /* SIOCSIFMTU */ - return compat_sys_ioctl(fd, SIOCSIFMTU, arg); - case 22: /* SIOCGIFMTU */ - return compat_sys_ioctl(fd, SIOCGIFMTU, arg); - case 23: /* SIOCGIFBRDADDR */ - return compat_sys_ioctl(fd, SIOCGIFBRDADDR, arg); - case 24: /* SIOCSIFBRDADDR */ - return compat_sys_ioctl(fd, SIOCSIFBRDADDR, arg); - case 25: /* SIOCGIFNETMASK */ - return compat_sys_ioctl(fd, SIOCGIFNETMASK, arg); - case 26: /* SIOCSIFNETMASK */ - return compat_sys_ioctl(fd, SIOCSIFNETMASK, arg); - case 27: /* SIOCGIFMETRIC */ - return compat_sys_ioctl(fd, SIOCGIFMETRIC, arg); - case 28: /* SIOCSIFMETRIC */ - return compat_sys_ioctl(fd, SIOCSIFMETRIC, arg); - case 30: /* SIOCSARP */ - return compat_sys_ioctl(fd, SIOCSARP, arg); - case 31: /* SIOCGARP */ - return compat_sys_ioctl(fd, SIOCGARP, arg); - case 32: /* SIOCDARP */ - return compat_sys_ioctl(fd, SIOCDARP, arg); - case 52: /* SIOCGETNAME */ - case 53: /* SIOCGETPEER */ - { - struct sockaddr uaddr; - int uaddr_len = sizeof(struct sockaddr), ret; - long args[3]; - mm_segment_t old_fs = get_fs(); - int (*sys_socketcall)(int, unsigned long *) = - (int (*)(int, unsigned long *))SYS(socketcall); - - args[0] = fd; args[1] = (long)&uaddr; args[2] = (long)&uaddr_len; - set_fs(KERNEL_DS); - ret = sys_socketcall(((cmd & 0xff) == 52) ? SYS_GETSOCKNAME : SYS_GETPEERNAME, - args); - set_fs(old_fs); - if (ret >= 0) { - if (copy_to_user(A(arg), &uaddr, uaddr_len)) - return -EFAULT; - } - return ret; - } -#if 0 - case 86: /* SIOCSOCKSYS */ - return socksys_syscall(fd, arg); -#endif - case 87: /* SIOCGIFNUM */ - { - struct net_device *d; - int i = 0; - - read_lock_bh(&dev_base_lock); - for_each_netdev(&init_net, d) - i++; - read_unlock_bh(&dev_base_lock); - - if (put_user (i, (int __user *)A(arg))) - return -EFAULT; - return 0; - } - } - return -ENOSYS; -} - -static int solaris_m(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret; - - switch (cmd & 0xff) { - case 1: /* MTIOCTOP */ - ret = sys_ioctl(fd, MTIOCTOP, (unsigned long)&arg); - break; - case 2: /* MTIOCGET */ - ret = sys_ioctl(fd, MTIOCGET, (unsigned long)&arg); - break; - case 3: /* MTIOCGETDRIVETYPE */ - case 4: /* MTIOCPERSISTENT */ - case 5: /* MTIOCPERSISTENTSTATUS */ - case 6: /* MTIOCLRERR */ - case 7: /* MTIOCGUARANTEEDORDER */ - case 8: /* MTIOCRESERVE */ - case 9: /* MTIOCRELEASE */ - case 10: /* MTIOCFORCERESERVE */ - case 13: /* MTIOCSTATE */ - case 14: /* MTIOCREADIGNOREILI */ - case 15: /* MTIOCREADIGNOREEOFS */ - case 16: /* MTIOCSHORTFMK */ - default: - ret = -ENOSYS; /* linux doesn't support these */ - break; - }; - - return ret; -} - -static int solaris_O(unsigned int fd, unsigned int cmd, u32 arg) -{ - int ret = -EINVAL; - - switch (cmd & 0xff) { - case 1: /* OPROMGETOPT */ - ret = sys_ioctl(fd, OPROMGETOPT, arg); - break; - case 2: /* OPROMSETOPT */ - ret = sys_ioctl(fd, OPROMSETOPT, arg); - break; - case 3: /* OPROMNXTOPT */ - ret = sys_ioctl(fd, OPROMNXTOPT, arg); - break; - case 4: /* OPROMSETOPT2 */ - ret = sys_ioctl(fd, OPROMSETOPT2, arg); - break; - case 5: /* OPROMNEXT */ - ret = sys_ioctl(fd, OPROMNEXT, arg); - break; - case 6: /* OPROMCHILD */ - ret = sys_ioctl(fd, OPROMCHILD, arg); - break; - case 7: /* OPROMGETPROP */ - ret = sys_ioctl(fd, OPROMGETPROP, arg); - break; - case 8: /* OPROMNXTPROP */ - ret = sys_ioctl(fd, OPROMNXTPROP, arg); - break; - case 9: /* OPROMU2P */ - ret = sys_ioctl(fd, OPROMU2P, arg); - break; - case 10: /* OPROMGETCONS */ - ret = sys_ioctl(fd, OPROMGETCONS, arg); - break; - case 11: /* OPROMGETFBNAME */ - ret = sys_ioctl(fd, OPROMGETFBNAME, arg); - break; - case 12: /* OPROMGETBOOTARGS */ - ret = sys_ioctl(fd, OPROMGETBOOTARGS, arg); - break; - case 13: /* OPROMGETVERSION */ - case 14: /* OPROMPATH2DRV */ - case 15: /* OPROMDEV2PROMNAME */ - case 16: /* OPROMPROM2DEVNAME */ - case 17: /* OPROMGETPROPLEN */ - default: - ret = -EINVAL; - break; - }; - return ret; -} - -/* }}} */ - -asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg) -{ - struct file *filp; - int error = -EBADF; - - filp = fget(fd); - if (!filp) - goto out; - - lock_kernel(); - error = -EFAULT; - switch ((cmd >> 8) & 0xff) { - case 'S': error = solaris_S(filp, fd, cmd, arg); break; - case 'T': error = solaris_T(fd, cmd, arg); break; - case 'i': error = solaris_i(fd, cmd, arg); break; - case 'r': error = solaris_r(fd, cmd, arg); break; - case 's': error = solaris_s(fd, cmd, arg); break; - case 't': error = solaris_t(fd, cmd, arg); break; - case 'f': error = sys_ioctl(fd, cmd, arg); break; - case 'm': error = solaris_m(fd, cmd, arg); break; - case 'O': error = solaris_O(fd, cmd, arg); break; - default: - error = -ENOSYS; - break; - } - unlock_kernel(); - fput(filp); -out: - if (error == -ENOSYS) { - unsigned char c = cmd>>8; - - if (c < ' ' || c > 126) c = '.'; - printk("solaris_ioctl: Unknown cmd fd(%d) cmd(%08x '%c') arg(%08x)\n", - (int)fd, (unsigned int)cmd, c, (unsigned int)arg); - error = -EINVAL; - } - return error; -} diff --git a/arch/sparc64/solaris/ipc.c b/arch/sparc64/solaris/ipc.c deleted file mode 100644 index 499135fa7060..000000000000 --- a/arch/sparc64/solaris/ipc.c +++ /dev/null @@ -1,126 +0,0 @@ -/* $Id: ipc.c,v 1.5 1999/12/09 00:41:00 davem Exp $ - * ipc.c: Solaris IPC emulation - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "conv.h" - -struct solaris_ipc_perm { - s32 uid; - s32 gid; - s32 cuid; - s32 cgid; - u32 mode; - u32 seq; - int key; - s32 pad[4]; -}; - -struct solaris_shmid_ds { - struct solaris_ipc_perm shm_perm; - int shm_segsz; - u32 shm_amp; - unsigned short shm_lkcnt; - char __padxx[2]; - s32 shm_lpid; - s32 shm_cpid; - u32 shm_nattch; - u32 shm_cnattch; - s32 shm_atime; - s32 shm_pad1; - s32 shm_dtime; - s32 shm_pad2; - s32 shm_ctime; - s32 shm_pad3; - unsigned short shm_cv; - char shm_pad4[2]; - u32 shm_sptas; - s32 shm_pad5[2]; -}; - -asmlinkage long solaris_shmsys(int cmd, u32 arg1, u32 arg2, u32 arg3) -{ - int (*sys_ipc)(unsigned,int,int,unsigned long,void __user *,long) = - (int (*)(unsigned,int,int,unsigned long,void __user *,long))SYS(ipc); - mm_segment_t old_fs; - unsigned long raddr; - int ret; - - switch (cmd) { - case 0: /* shmat */ - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ipc(SHMAT, arg1, arg3 & ~0x4000, (unsigned long)&raddr, A(arg2), 0); - set_fs(old_fs); - if (ret >= 0) return (u32)raddr; - else return ret; - case 1: /* shmctl */ - switch (arg2) { - case 3: /* SHM_LOCK */ - case 4: /* SHM_UNLOCK */ - return sys_ipc(SHMCTL, arg1, (arg2 == 3) ? SHM_LOCK : SHM_UNLOCK, 0, NULL, 0); - case 10: /* IPC_RMID */ - return sys_ipc(SHMCTL, arg1, IPC_RMID, 0, NULL, 0); - case 11: /* IPC_SET */ - { - struct shmid_ds s; - struct solaris_shmid_ds __user *p = A(arg3); - - if (get_user (s.shm_perm.uid, &p->shm_perm.uid) || - __get_user (s.shm_perm.gid, &p->shm_perm.gid) || - __get_user (s.shm_perm.mode, &p->shm_perm.mode)) - return -EFAULT; - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0); - set_fs(old_fs); - return ret; - } - case 12: /* IPC_STAT */ - { - struct shmid_ds s; - struct solaris_shmid_ds __user *p = A(arg3); - - old_fs = get_fs(); - set_fs(KERNEL_DS); - ret = sys_ipc(SHMCTL, arg1, IPC_SET, 0, &s, 0); - set_fs(old_fs); - if (put_user (s.shm_perm.uid, &(p->shm_perm.uid)) || - __put_user (s.shm_perm.gid, &(p->shm_perm.gid)) || - __put_user (s.shm_perm.cuid, &(p->shm_perm.cuid)) || - __put_user (s.shm_perm.cgid, &(p->shm_perm.cgid)) || - __put_user (s.shm_perm.mode, &(p->shm_perm.mode)) || - __put_user (s.shm_perm.seq, &(p->shm_perm.seq)) || - __put_user (s.shm_perm.key, &(p->shm_perm.key)) || - __put_user (s.shm_segsz, &(p->shm_segsz)) || - __put_user (s.shm_lpid, &(p->shm_lpid)) || - __put_user (s.shm_cpid, &(p->shm_cpid)) || - __put_user (s.shm_nattch, &(p->shm_nattch)) || - __put_user (s.shm_atime, &(p->shm_atime)) || - __put_user (s.shm_dtime, &(p->shm_dtime)) || - __put_user (s.shm_ctime, &(p->shm_ctime))) - return -EFAULT; - return ret; - } - default: return -EINVAL; - } - case 2: /* shmdt */ - return sys_ipc(SHMDT, 0, 0, 0, A(arg1), 0); - case 3: /* shmget */ - return sys_ipc(SHMGET, arg1, arg2, arg3, NULL, 0); - } - return -EINVAL; -} diff --git a/arch/sparc64/solaris/misc.c b/arch/sparc64/solaris/misc.c deleted file mode 100644 index d3e48e9701bf..000000000000 --- a/arch/sparc64/solaris/misc.c +++ /dev/null @@ -1,786 +0,0 @@ -/* $Id: misc.c,v 1.36 2002/02/09 19:49:31 davem Exp $ - * misc.c: Miscellaneous syscall emulation for Solaris - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "conv.h" - -/* Conversion from Linux to Solaris errnos. 0-34 are identity mapped. - Some Linux errnos (EPROCLIM, EDOTDOT, ERREMOTE, EUCLEAN, ENOTNAM, - ENAVAIL, EISNAM, EREMOTEIO, ENOMEDIUM, EMEDIUMTYPE) have no Solaris - equivalents. I return EINVAL in that case, which is very wrong. If - someone suggest a better value for them, you're welcomed. - On the other side, Solaris ECANCELED and ENOTSUP have no Linux equivalents, - but that doesn't matter here. --jj */ -int solaris_err_table[] = { -/* 0 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -/* 10 */ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -/* 20 */ 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, -/* 30 */ 30, 31, 32, 33, 34, 22, 150, 149, 95, 96, -/* 40 */ 97, 98, 99, 120, 121, 122, 123, 124, 125, 126, -/* 50 */ 127, 128, 129, 130, 131, 132, 133, 134, 143, 144, -/* 60 */ 145, 146, 90, 78, 147, 148, 93, 22, 94, 49, -/* 70 */ 151, 66, 60, 62, 63, 35, 77, 36, 45, 46, -/* 80 */ 64, 22, 67, 68, 69, 70, 71, 74, 22, 82, -/* 90 */ 89, 92, 79, 81, 37, 38, 39, 40, 41, 42, -/* 100 */ 43, 44, 50, 51, 52, 53, 54, 55, 56, 57, -/* 110 */ 87, 61, 84, 65, 83, 80, 91, 22, 22, 22, -/* 120 */ 22, 22, 88, 86, 85, 22, 22, -}; - -#define SOLARIS_NR_OPEN 256 - -static u32 do_solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u64 off) -{ - struct file *file = NULL; - unsigned long retval, ret_type; - - /* Do we need it here? */ - set_personality(PER_SVR4); - if (flags & MAP_NORESERVE) { - static int cnt; - - if (cnt < 5) { - printk("%s: unimplemented Solaris MAP_NORESERVE mmap() flag\n", - current->comm); - cnt++; - } - flags &= ~MAP_NORESERVE; - } - retval = -EBADF; - if(!(flags & MAP_ANONYMOUS)) { - if(fd >= SOLARIS_NR_OPEN) - goto out; - file = fget(fd); - if (!file) - goto out; - else { - struct inode * inode = file->f_path.dentry->d_inode; - if(imajor(inode) == MEM_MAJOR && - iminor(inode) == 5) { - flags |= MAP_ANONYMOUS; - fput(file); - file = NULL; - } - } - } - - retval = -EINVAL; - len = PAGE_ALIGN(len); - if(!(flags & MAP_FIXED)) - addr = 0; - else if (len > STACK_TOP32 || addr > STACK_TOP32 - len) - goto out_putf; - ret_type = flags & _MAP_NEW; - flags &= ~_MAP_NEW; - - down_write(¤t->mm->mmap_sem); - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - retval = do_mmap(file, - (unsigned long) addr, (unsigned long) len, - (unsigned long) prot, (unsigned long) flags, off); - up_write(¤t->mm->mmap_sem); - if(!ret_type) - retval = ((retval < STACK_TOP32) ? 0 : retval); - -out_putf: - if (file) - fput(file); -out: - return (u32) retval; -} - -asmlinkage u32 solaris_mmap(u32 addr, u32 len, u32 prot, u32 flags, u32 fd, u32 off) -{ - return do_solaris_mmap(addr, len, prot, flags, fd, (u64) off); -} - -asmlinkage u32 solaris_mmap64(struct pt_regs *regs, u32 len, u32 prot, u32 flags, u32 fd, u32 offhi) -{ - u32 offlo; - - if (regs->u_regs[UREG_G1]) { - if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x5c))) - return -EFAULT; - } else { - if (get_user (offlo, (u32 __user *)(long)((u32)regs->u_regs[UREG_I6] + 0x60))) - return -EFAULT; - } - return do_solaris_mmap((u32)regs->u_regs[UREG_I0], len, prot, flags, fd, (((u64)offhi)<<32)|offlo); -} - -asmlinkage int solaris_brk(u32 brk) -{ - int (*sunos_brk)(u32) = (int (*)(u32))SUNOS(17); - - return sunos_brk(brk); -} - -static int __set_utsfield(char __user *to, int to_size, - const char *from, int from_size, - int dotchop, int countfrom) -{ - int len = countfrom ? (to_size > from_size ? - from_size : to_size) : to_size; - int off; - - if (copy_to_user(to, from, len)) - return -EFAULT; - - off = len < to_size? len: len - 1; - if (dotchop) { - const char *p = strnchr(from, len, '.'); - if (p) off = p - from; - } - - if (__put_user('\0', to + off)) - return -EFAULT; - - return 0; -} - -#define set_utsfield(to, from, dotchop, countfrom) \ - __set_utsfield((to), sizeof(to), \ - (from), sizeof(from), \ - (dotchop), (countfrom)) - -struct sol_uname { - char sysname[9]; - char nodename[9]; - char release[9]; - char version[9]; - char machine[9]; -}; - -struct sol_utsname { - char sysname[257]; - char nodename[257]; - char release[257]; - char version[257]; - char machine[257]; -}; - -static char *machine(void) -{ - switch (sparc_cpu_model) { - case sun4: return "sun4"; - case sun4c: return "sun4c"; - case sun4e: return "sun4e"; - case sun4m: return "sun4m"; - case sun4d: return "sun4d"; - case sun4u: return "sun4u"; - default: return "sparc"; - } -} - -static char *platform(char *buffer, int sz) -{ - struct device_node *dp = of_find_node_by_path("/"); - int len; - - *buffer = 0; - len = strlen(dp->name); - if (len > sz) - len = sz; - memcpy(buffer, dp->name, len); - buffer[len] = 0; - if (*buffer) { - char *p; - - for (p = buffer; *p; p++) - if (*p == '/' || *p == ' ') *p = '_'; - return buffer; - } - - return "sun4u"; -} - -static char *serial(char *buffer, int sz) -{ - struct device_node *dp = of_find_node_by_path("/options"); - int len; - - *buffer = 0; - if (dp) { - const char *val = - of_get_property(dp, "system-board-serial#", &len); - - if (val && len > 0) { - if (len > sz) - len = sz; - memcpy(buffer, val, len); - buffer[len] = 0; - } - } - if (!*buffer) - return "4512348717234"; - else - return buffer; -} - -asmlinkage int solaris_utssys(u32 buf, u32 flags, int which, u32 buf2) -{ - struct sol_uname __user *v = A(buf); - int err; - - switch (which) { - case 0: /* old uname */ - /* Let's cheat */ - err = set_utsfield(v->sysname, "SunOS", 1, 0); - down_read(&uts_sem); - err |= set_utsfield(v->nodename, utsname()->nodename, - 1, 1); - up_read(&uts_sem); - err |= set_utsfield(v->release, "2.6", 0, 0); - err |= set_utsfield(v->version, "Generic", 0, 0); - err |= set_utsfield(v->machine, machine(), 0, 0); - return (err ? -EFAULT : 0); - case 2: /* ustat */ - return -ENOSYS; - case 3: /* fusers */ - return -ENOSYS; - default: - return -ENOSYS; - } -} - -asmlinkage int solaris_utsname(u32 buf) -{ - struct sol_utsname __user *v = A(buf); - int err; - - /* Why should we not lie a bit? */ - down_read(&uts_sem); - err = set_utsfield(v->sysname, "SunOS", 0, 0); - err |= set_utsfield(v->nodename, utsname()->nodename, 1, 1); - err |= set_utsfield(v->release, "5.6", 0, 0); - err |= set_utsfield(v->version, "Generic", 0, 0); - err |= set_utsfield(v->machine, machine(), 0, 0); - up_read(&uts_sem); - - return (err ? -EFAULT : 0); -} - -#define SI_SYSNAME 1 /* return name of operating system */ -#define SI_HOSTNAME 2 /* return name of node */ -#define SI_RELEASE 3 /* return release of operating system */ -#define SI_VERSION 4 /* return version field of utsname */ -#define SI_MACHINE 5 /* return kind of machine */ -#define SI_ARCHITECTURE 6 /* return instruction set arch */ -#define SI_HW_SERIAL 7 /* return hardware serial number */ -#define SI_HW_PROVIDER 8 /* return hardware manufacturer */ -#define SI_SRPC_DOMAIN 9 /* return secure RPC domain */ -#define SI_PLATFORM 513 /* return platform identifier */ - -asmlinkage int solaris_sysinfo(int cmd, u32 buf, s32 count) -{ - char *p, *q, *r; - char buffer[256]; - int len; - - /* Again, we cheat :)) */ - switch (cmd) { - case SI_SYSNAME: r = "SunOS"; break; - case SI_HOSTNAME: - r = buffer + 256; - down_read(&uts_sem); - for (p = utsname()->nodename, q = buffer; - q < r && *p && *p != '.'; *q++ = *p++); - up_read(&uts_sem); - *q = 0; - r = buffer; - break; - case SI_RELEASE: r = "5.6"; break; - case SI_MACHINE: r = machine(); break; - case SI_ARCHITECTURE: r = "sparc"; break; - case SI_HW_PROVIDER: r = "Sun_Microsystems"; break; - case SI_HW_SERIAL: r = serial(buffer, sizeof(buffer)); break; - case SI_PLATFORM: r = platform(buffer, sizeof(buffer)); break; - case SI_SRPC_DOMAIN: r = ""; break; - case SI_VERSION: r = "Generic"; break; - default: return -EINVAL; - } - len = strlen(r) + 1; - if (count < len) { - if (copy_to_user(A(buf), r, count - 1) || - __put_user(0, (char __user *)A(buf) + count - 1)) - return -EFAULT; - } else { - if (copy_to_user(A(buf), r, len)) - return -EFAULT; - } - return len; -} - -#define SOLARIS_CONFIG_NGROUPS 2 -#define SOLARIS_CONFIG_CHILD_MAX 3 -#define SOLARIS_CONFIG_OPEN_FILES 4 -#define SOLARIS_CONFIG_POSIX_VER 5 -#define SOLARIS_CONFIG_PAGESIZE 6 -#define SOLARIS_CONFIG_CLK_TCK 7 -#define SOLARIS_CONFIG_XOPEN_VER 8 -#define SOLARIS_CONFIG_PROF_TCK 10 -#define SOLARIS_CONFIG_NPROC_CONF 11 -#define SOLARIS_CONFIG_NPROC_ONLN 12 -#define SOLARIS_CONFIG_AIO_LISTIO_MAX 13 -#define SOLARIS_CONFIG_AIO_MAX 14 -#define SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX 15 -#define SOLARIS_CONFIG_DELAYTIMER_MAX 16 -#define SOLARIS_CONFIG_MQ_OPEN_MAX 17 -#define SOLARIS_CONFIG_MQ_PRIO_MAX 18 -#define SOLARIS_CONFIG_RTSIG_MAX 19 -#define SOLARIS_CONFIG_SEM_NSEMS_MAX 20 -#define SOLARIS_CONFIG_SEM_VALUE_MAX 21 -#define SOLARIS_CONFIG_SIGQUEUE_MAX 22 -#define SOLARIS_CONFIG_SIGRT_MIN 23 -#define SOLARIS_CONFIG_SIGRT_MAX 24 -#define SOLARIS_CONFIG_TIMER_MAX 25 -#define SOLARIS_CONFIG_PHYS_PAGES 26 -#define SOLARIS_CONFIG_AVPHYS_PAGES 27 - -asmlinkage int solaris_sysconf(int id) -{ - switch (id) { - case SOLARIS_CONFIG_NGROUPS: return NGROUPS_MAX; - case SOLARIS_CONFIG_CHILD_MAX: - return current->signal->rlim[RLIMIT_NPROC].rlim_cur; - case SOLARIS_CONFIG_OPEN_FILES: - return current->signal->rlim[RLIMIT_NOFILE].rlim_cur; - case SOLARIS_CONFIG_POSIX_VER: return 199309; - case SOLARIS_CONFIG_PAGESIZE: return PAGE_SIZE; - case SOLARIS_CONFIG_XOPEN_VER: return 3; - case SOLARIS_CONFIG_CLK_TCK: - case SOLARIS_CONFIG_PROF_TCK: - return sparc64_get_clock_tick(smp_processor_id()); -#ifdef CONFIG_SMP - case SOLARIS_CONFIG_NPROC_CONF: return NR_CPUS; - case SOLARIS_CONFIG_NPROC_ONLN: return num_online_cpus(); -#else - case SOLARIS_CONFIG_NPROC_CONF: return 1; - case SOLARIS_CONFIG_NPROC_ONLN: return 1; -#endif - case SOLARIS_CONFIG_SIGRT_MIN: return 37; - case SOLARIS_CONFIG_SIGRT_MAX: return 44; - case SOLARIS_CONFIG_PHYS_PAGES: - case SOLARIS_CONFIG_AVPHYS_PAGES: - { - struct sysinfo s; - - si_meminfo(&s); - if (id == SOLARIS_CONFIG_PHYS_PAGES) - return s.totalram >>= PAGE_SHIFT; - else - return s.freeram >>= PAGE_SHIFT; - } - /* XXX support these as well -jj */ - case SOLARIS_CONFIG_AIO_LISTIO_MAX: return -EINVAL; - case SOLARIS_CONFIG_AIO_MAX: return -EINVAL; - case SOLARIS_CONFIG_AIO_PRIO_DELTA_MAX: return -EINVAL; - case SOLARIS_CONFIG_DELAYTIMER_MAX: return -EINVAL; - case SOLARIS_CONFIG_MQ_OPEN_MAX: return -EINVAL; - case SOLARIS_CONFIG_MQ_PRIO_MAX: return -EINVAL; - case SOLARIS_CONFIG_RTSIG_MAX: return -EINVAL; - case SOLARIS_CONFIG_SEM_NSEMS_MAX: return -EINVAL; - case SOLARIS_CONFIG_SEM_VALUE_MAX: return -EINVAL; - case SOLARIS_CONFIG_SIGQUEUE_MAX: return -EINVAL; - case SOLARIS_CONFIG_TIMER_MAX: return -EINVAL; - default: return -EINVAL; - } -} - -asmlinkage int solaris_procids(int cmd, s32 pid, s32 pgid) -{ - int ret; - - switch (cmd) { - case 0: /* getpgrp */ - return task_pgrp_vnr(current); - case 1: /* setpgrp */ - { - int (*sys_setpgid)(pid_t,pid_t) = - (int (*)(pid_t,pid_t))SYS(setpgid); - - /* can anyone explain me the difference between - Solaris setpgrp and setsid? */ - ret = sys_setpgid(0, 0); - if (ret) return ret; - proc_clear_tty(current); - return task_pgrp_vnr(current); - } - case 2: /* getsid */ - { - int (*sys_getsid)(pid_t) = (int (*)(pid_t))SYS(getsid); - return sys_getsid(pid); - } - case 3: /* setsid */ - { - int (*sys_setsid)(void) = (int (*)(void))SYS(setsid); - return sys_setsid(); - } - case 4: /* getpgid */ - { - int (*sys_getpgid)(pid_t) = (int (*)(pid_t))SYS(getpgid); - return sys_getpgid(pid); - } - case 5: /* setpgid */ - { - int (*sys_setpgid)(pid_t,pid_t) = - (int (*)(pid_t,pid_t))SYS(setpgid); - return sys_setpgid(pid,pgid); - } - } - return -EINVAL; -} - -asmlinkage int solaris_gettimeofday(u32 tim) -{ - int (*sys_gettimeofday)(struct timeval *, struct timezone *) = - (int (*)(struct timeval *, struct timezone *))SYS(gettimeofday); - - return sys_gettimeofday((struct timeval *)(u64)tim, NULL); -} - -#define RLIM_SOL_INFINITY32 0x7fffffff -#define RLIM_SOL_SAVED_MAX32 0x7ffffffe -#define RLIM_SOL_SAVED_CUR32 0x7ffffffd -#define RLIM_SOL_INFINITY ((u64)-3) -#define RLIM_SOL_SAVED_MAX ((u64)-2) -#define RLIM_SOL_SAVED_CUR ((u64)-1) -#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x) -#define RLIMIT_SOL_NOFILE 5 -#define RLIMIT_SOL_VMEM 6 - -struct rlimit32 { - u32 rlim_cur; - u32 rlim_max; -}; - -asmlinkage int solaris_getrlimit(unsigned int resource, struct rlimit32 __user *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - int (*sys_getrlimit)(unsigned int, struct rlimit *) = - (int (*)(unsigned int, struct rlimit *))SYS(getrlimit); - - if (resource > RLIMIT_SOL_VMEM) - return -EINVAL; - switch (resource) { - case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break; - case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break; - default: break; - } - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs (old_fs); - if (!ret) { - if (r.rlim_cur == RLIM_INFINITY) - r.rlim_cur = RLIM_SOL_INFINITY32; - else if ((u64)r.rlim_cur > RLIM_SOL_INFINITY32) - r.rlim_cur = RLIM_SOL_SAVED_CUR32; - if (r.rlim_max == RLIM_INFINITY) - r.rlim_max = RLIM_SOL_INFINITY32; - else if ((u64)r.rlim_max > RLIM_SOL_INFINITY32) - r.rlim_max = RLIM_SOL_SAVED_MAX32; - ret = put_user (r.rlim_cur, &rlim->rlim_cur); - ret |= __put_user (r.rlim_max, &rlim->rlim_max); - } - return ret; -} - -asmlinkage int solaris_setrlimit(unsigned int resource, struct rlimit32 __user *rlim) -{ - struct rlimit r, rold; - int ret; - mm_segment_t old_fs = get_fs (); - int (*sys_getrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit); - int (*sys_setrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit); - - if (resource > RLIMIT_SOL_VMEM) - return -EINVAL; - switch (resource) { - case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break; - case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break; - default: break; - } - if (get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &rold); - if (!ret) { - if (r.rlim_cur == RLIM_SOL_INFINITY32) - r.rlim_cur = RLIM_INFINITY; - else if (r.rlim_cur == RLIM_SOL_SAVED_CUR32) - r.rlim_cur = rold.rlim_cur; - else if (r.rlim_cur == RLIM_SOL_SAVED_MAX32) - r.rlim_cur = rold.rlim_max; - if (r.rlim_max == RLIM_SOL_INFINITY32) - r.rlim_max = RLIM_INFINITY; - else if (r.rlim_max == RLIM_SOL_SAVED_CUR32) - r.rlim_max = rold.rlim_cur; - else if (r.rlim_max == RLIM_SOL_SAVED_MAX32) - r.rlim_max = rold.rlim_max; - ret = sys_setrlimit(resource, &r); - } - set_fs (old_fs); - return ret; -} - -asmlinkage int solaris_getrlimit64(unsigned int resource, struct rlimit __user *rlim) -{ - struct rlimit r; - int ret; - mm_segment_t old_fs = get_fs (); - int (*sys_getrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit); - - if (resource > RLIMIT_SOL_VMEM) - return -EINVAL; - switch (resource) { - case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break; - case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break; - default: break; - } - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &r); - set_fs (old_fs); - if (!ret) { - if (r.rlim_cur == RLIM_INFINITY) - r.rlim_cur = RLIM_SOL_INFINITY; - if (r.rlim_max == RLIM_INFINITY) - r.rlim_max = RLIM_SOL_INFINITY; - ret = put_user (r.rlim_cur, &rlim->rlim_cur); - ret |= __put_user (r.rlim_max, &rlim->rlim_max); - } - return ret; -} - -asmlinkage int solaris_setrlimit64(unsigned int resource, struct rlimit __user *rlim) -{ - struct rlimit r, rold; - int ret; - mm_segment_t old_fs = get_fs (); - int (*sys_getrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(getrlimit); - int (*sys_setrlimit)(unsigned int, struct rlimit __user *) = - (int (*)(unsigned int, struct rlimit __user *))SYS(setrlimit); - - if (resource > RLIMIT_SOL_VMEM) - return -EINVAL; - switch (resource) { - case RLIMIT_SOL_NOFILE: resource = RLIMIT_NOFILE; break; - case RLIMIT_SOL_VMEM: resource = RLIMIT_AS; break; - default: break; - } - if (get_user (r.rlim_cur, &rlim->rlim_cur) || - __get_user (r.rlim_max, &rlim->rlim_max)) - return -EFAULT; - set_fs (KERNEL_DS); - ret = sys_getrlimit(resource, &rold); - if (!ret) { - if (r.rlim_cur == RLIM_SOL_INFINITY) - r.rlim_cur = RLIM_INFINITY; - else if (r.rlim_cur == RLIM_SOL_SAVED_CUR) - r.rlim_cur = rold.rlim_cur; - else if (r.rlim_cur == RLIM_SOL_SAVED_MAX) - r.rlim_cur = rold.rlim_max; - if (r.rlim_max == RLIM_SOL_INFINITY) - r.rlim_max = RLIM_INFINITY; - else if (r.rlim_max == RLIM_SOL_SAVED_CUR) - r.rlim_max = rold.rlim_cur; - else if (r.rlim_max == RLIM_SOL_SAVED_MAX) - r.rlim_max = rold.rlim_max; - ret = sys_setrlimit(resource, &r); - } - set_fs (old_fs); - return ret; -} - -struct sol_ntptimeval { - struct compat_timeval time; - s32 maxerror; - s32 esterror; -}; - -struct sol_timex { - u32 modes; - s32 offset; - s32 freq; - s32 maxerror; - s32 esterror; - s32 status; - s32 constant; - s32 precision; - s32 tolerance; - s32 ppsfreq; - s32 jitter; - s32 shift; - s32 stabil; - s32 jitcnt; - s32 calcnt; - s32 errcnt; - s32 stbcnt; -}; - -asmlinkage int solaris_ntp_gettime(struct sol_ntptimeval __user *ntp) -{ - int (*sys_adjtimex)(struct timex __user *) = - (int (*)(struct timex __user *))SYS(adjtimex); - struct timex t; - int ret; - mm_segment_t old_fs = get_fs(); - - set_fs(KERNEL_DS); - t.modes = 0; - ret = sys_adjtimex(&t); - set_fs(old_fs); - if (ret < 0) - return ret; - ret = put_user (t.time.tv_sec, &ntp->time.tv_sec); - ret |= __put_user (t.time.tv_usec, &ntp->time.tv_usec); - ret |= __put_user (t.maxerror, &ntp->maxerror); - ret |= __put_user (t.esterror, &ntp->esterror); - return ret; -} - -asmlinkage int solaris_ntp_adjtime(struct sol_timex __user *txp) -{ - int (*sys_adjtimex)(struct timex __user *) = - (int (*)(struct timex __user *))SYS(adjtimex); - struct timex t; - int ret, err; - mm_segment_t old_fs = get_fs(); - - ret = get_user (t.modes, &txp->modes); - ret |= __get_user (t.offset, &txp->offset); - ret |= __get_user (t.freq, &txp->freq); - ret |= __get_user (t.maxerror, &txp->maxerror); - ret |= __get_user (t.esterror, &txp->esterror); - ret |= __get_user (t.status, &txp->status); - ret |= __get_user (t.constant, &txp->constant); - set_fs(KERNEL_DS); - ret = sys_adjtimex(&t); - set_fs(old_fs); - if (ret < 0) - return ret; - err = put_user (t.offset, &txp->offset); - err |= __put_user (t.freq, &txp->freq); - err |= __put_user (t.maxerror, &txp->maxerror); - err |= __put_user (t.esterror, &txp->esterror); - err |= __put_user (t.status, &txp->status); - err |= __put_user (t.constant, &txp->constant); - err |= __put_user (t.precision, &txp->precision); - err |= __put_user (t.tolerance, &txp->tolerance); - err |= __put_user (t.ppsfreq, &txp->ppsfreq); - err |= __put_user (t.jitter, &txp->jitter); - err |= __put_user (t.shift, &txp->shift); - err |= __put_user (t.stabil, &txp->stabil); - err |= __put_user (t.jitcnt, &txp->jitcnt); - err |= __put_user (t.calcnt, &txp->calcnt); - err |= __put_user (t.errcnt, &txp->errcnt); - err |= __put_user (t.stbcnt, &txp->stbcnt); - if (err) - return -EFAULT; - return ret; -} - -asmlinkage int do_sol_unimplemented(struct pt_regs *regs) -{ - printk ("Unimplemented Solaris syscall %d %08x %08x %08x %08x\n", - (int)regs->u_regs[UREG_G1], - (int)regs->u_regs[UREG_I0], - (int)regs->u_regs[UREG_I1], - (int)regs->u_regs[UREG_I2], - (int)regs->u_regs[UREG_I3]); - return -ENOSYS; -} - -asmlinkage void solaris_register(void) -{ - set_personality(PER_SVR4); -} - -extern long solaris_to_linux_signals[], linux_to_solaris_signals[]; - -struct exec_domain solaris_exec_domain = { - .name = "Solaris", - .handler = NULL, - .pers_low = 1, /* PER_SVR4 personality */ - .pers_high = 1, - .signal_map = solaris_to_linux_signals, - .signal_invmap =linux_to_solaris_signals, - .module = THIS_MODULE, - .next = NULL -}; - -extern int init_socksys(void); - -MODULE_AUTHOR("Jakub Jelinek (jj@ultra.linux.cz), Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz)"); -MODULE_DESCRIPTION("Solaris binary emulation module"); -MODULE_LICENSE("GPL"); - -extern u32 tl0_solaris[8]; -#define update_ttable(x) \ - tl0_solaris[3] = (((long)(x) - (long)tl0_solaris - 3) >> 2) | 0x40000000; \ - wmb(); \ - __asm__ __volatile__ ("flush %0" : : "r" (&tl0_solaris[3])) - -extern u32 solaris_sparc_syscall[]; -extern u32 solaris_syscall[]; -extern void cleanup_socksys(void); - -extern u32 entry64_personality_patch; - -static int __init solaris_init(void) -{ - int ret; - - SOLDD(("Solaris module at %p\n", solaris_sparc_syscall)); - register_exec_domain(&solaris_exec_domain); - if ((ret = init_socksys())) { - unregister_exec_domain(&solaris_exec_domain); - return ret; - } - update_ttable(solaris_sparc_syscall); - entry64_personality_patch |= - (offsetof(struct task_struct, personality) + - (sizeof(unsigned long) - 1)); - wmb(); - __asm__ __volatile__("flush %0" - : : "r" (&entry64_personality_patch)); - return 0; -} - -static void __exit solaris_exit(void) -{ - update_ttable(solaris_syscall); - cleanup_socksys(); - unregister_exec_domain(&solaris_exec_domain); -} - -module_init(solaris_init); -module_exit(solaris_exit); diff --git a/arch/sparc64/solaris/signal.c b/arch/sparc64/solaris/signal.c deleted file mode 100644 index de10c9716cfb..000000000000 --- a/arch/sparc64/solaris/signal.c +++ /dev/null @@ -1,429 +0,0 @@ -/* $Id: signal.c,v 1.7 2000/09/05 21:44:54 davem Exp $ - * signal.c: Signal emulation for Solaris - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#include -#include - -#include -#include -#include - -#include "conv.h" -#include "signal.h" - -#define _S(nr) (1L<<((nr)-1)) - -#define _BLOCKABLE (~(_S(SIGKILL) | _S(SIGSTOP))) - -long linux_to_solaris_signals[] = { - 0, - SOLARIS_SIGHUP, SOLARIS_SIGINT, - SOLARIS_SIGQUIT, SOLARIS_SIGILL, - SOLARIS_SIGTRAP, SOLARIS_SIGIOT, - SOLARIS_SIGEMT, SOLARIS_SIGFPE, - SOLARIS_SIGKILL, SOLARIS_SIGBUS, - SOLARIS_SIGSEGV, SOLARIS_SIGSYS, - SOLARIS_SIGPIPE, SOLARIS_SIGALRM, - SOLARIS_SIGTERM, SOLARIS_SIGURG, - SOLARIS_SIGSTOP, SOLARIS_SIGTSTP, - SOLARIS_SIGCONT, SOLARIS_SIGCLD, - SOLARIS_SIGTTIN, SOLARIS_SIGTTOU, - SOLARIS_SIGPOLL, SOLARIS_SIGXCPU, - SOLARIS_SIGXFSZ, SOLARIS_SIGVTALRM, - SOLARIS_SIGPROF, SOLARIS_SIGWINCH, - SOLARIS_SIGUSR1, SOLARIS_SIGUSR1, - SOLARIS_SIGUSR2, -1, -}; - -long solaris_to_linux_signals[] = { - 0, - SIGHUP, SIGINT, SIGQUIT, SIGILL, - SIGTRAP, SIGIOT, SIGEMT, SIGFPE, - SIGKILL, SIGBUS, SIGSEGV, SIGSYS, - SIGPIPE, SIGALRM, SIGTERM, SIGUSR1, - SIGUSR2, SIGCHLD, -1, SIGWINCH, - SIGURG, SIGPOLL, SIGSTOP, SIGTSTP, - SIGCONT, SIGTTIN, SIGTTOU, SIGVTALRM, - SIGPROF, SIGXCPU, SIGXFSZ, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, -}; - -static inline long mapsig(long sig) -{ - if ((unsigned long)sig > SOLARIS_NSIGNALS) - return -EINVAL; - return solaris_to_linux_signals[sig]; -} - -asmlinkage int solaris_kill(int pid, int sig) -{ - int (*sys_kill)(int,int) = - (int (*)(int,int))SYS(kill); - int s = mapsig(sig); - - if (s < 0) return s; - return sys_kill(pid, s); -} - -static long sig_handler(int sig, u32 arg, int one_shot) -{ - struct sigaction sa, old; - int ret; - mm_segment_t old_fs = get_fs(); - int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) = - (int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction); - - sigemptyset(&sa.sa_mask); - sa.sa_restorer = NULL; - sa.sa_handler = (__sighandler_t)A(arg); - sa.sa_flags = 0; - if (one_shot) sa.sa_flags = SA_ONESHOT | SA_NOMASK; - set_fs (KERNEL_DS); - ret = sys_sigaction(sig, (void __user *)&sa, (void __user *)&old); - set_fs (old_fs); - if (ret < 0) return ret; - return (u32)(unsigned long)old.sa_handler; -} - -static inline long solaris_signal(int sig, u32 arg) -{ - return sig_handler (sig, arg, 1); -} - -static long solaris_sigset(int sig, u32 arg) -{ - if (arg != 2) /* HOLD */ { - spin_lock_irq(¤t->sighand->siglock); - sigdelsetmask(¤t->blocked, _S(sig)); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return sig_handler (sig, arg, 0); - } else { - spin_lock_irq(¤t->sighand->siglock); - sigaddsetmask(¤t->blocked, (_S(sig) & ~_BLOCKABLE)); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return 0; - } -} - -static inline long solaris_sighold(int sig) -{ - return solaris_sigset(sig, 2); -} - -static inline long solaris_sigrelse(int sig) -{ - spin_lock_irq(¤t->sighand->siglock); - sigdelsetmask(¤t->blocked, _S(sig)); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - return 0; -} - -static inline long solaris_sigignore(int sig) -{ - return sig_handler(sig, (u32)(unsigned long)SIG_IGN, 0); -} - -static inline long solaris_sigpause(int sig) -{ - printk ("Need to support solaris sigpause\n"); - return -ENOSYS; -} - -asmlinkage long solaris_sigfunc(int sig, u32 arg) -{ - int func = sig & ~0xff; - - sig = mapsig(sig & 0xff); - if (sig < 0) return sig; - switch (func) { - case 0: return solaris_signal(sig, arg); - case 0x100: return solaris_sigset(sig, arg); - case 0x200: return solaris_sighold(sig); - case 0x400: return solaris_sigrelse(sig); - case 0x800: return solaris_sigignore(sig); - case 0x1000: return solaris_sigpause(sig); - } - return -EINVAL; -} - -typedef struct { - u32 __sigbits[4]; -} sol_sigset_t; - -static inline int mapin(u32 *p, sigset_t *q) -{ - int i; - u32 x; - int sig; - - sigemptyset(q); - x = p[0]; - for (i = 1; i <= SOLARIS_NSIGNALS; i++) { - if (x & 1) { - sig = solaris_to_linux_signals[i]; - if (sig == -1) - return -EINVAL; - sigaddsetmask(q, (1L << (sig - 1))); - } - x >>= 1; - if (i == 32) - x = p[1]; - } - return 0; -} - -static inline int mapout(sigset_t *q, u32 *p) -{ - int i; - int sig; - - p[0] = 0; - p[1] = 0; - for (i = 1; i <= 32; i++) { - if (sigismember(q, sigmask(i))) { - sig = linux_to_solaris_signals[i]; - if (sig == -1) - return -EINVAL; - if (sig > 32) - p[1] |= 1L << (sig - 33); - else - p[0] |= 1L << (sig - 1); - } - } - return 0; -} - -asmlinkage int solaris_sigprocmask(int how, u32 in, u32 out) -{ - sigset_t in_s, *ins, out_s, *outs; - mm_segment_t old_fs = get_fs(); - int ret; - int (*sys_sigprocmask)(int,sigset_t __user *,sigset_t __user *) = - (int (*)(int,sigset_t __user *,sigset_t __user *))SYS(sigprocmask); - - ins = NULL; outs = NULL; - if (in) { - u32 tmp[2]; - - if (copy_from_user (tmp, (void __user *)A(in), 2*sizeof(u32))) - return -EFAULT; - ins = &in_s; - if (mapin (tmp, ins)) return -EINVAL; - } - if (out) outs = &out_s; - set_fs (KERNEL_DS); - ret = sys_sigprocmask((how == 3) ? SIG_SETMASK : how, - (void __user *)ins, (void __user *)outs); - set_fs (old_fs); - if (ret) return ret; - if (out) { - u32 tmp[4]; - - tmp[2] = 0; tmp[3] = 0; - if (mapout (outs, tmp)) return -EINVAL; - if (copy_to_user((void __user *)A(out), tmp, 4*sizeof(u32))) - return -EFAULT; - } - return 0; -} - -asmlinkage long do_sol_sigsuspend(u32 mask) -{ - sigset_t s; - u32 tmp[2]; - - if (copy_from_user (tmp, (sol_sigset_t __user *)A(mask), 2*sizeof(u32))) - return -EFAULT; - if (mapin (tmp, &s)) return -EINVAL; - return (long)s.sig[0]; -} - -struct sol_sigaction { - int sa_flags; - u32 sa_handler; - u32 sa_mask[4]; - int sa_resv[2]; -}; - -asmlinkage int solaris_sigaction(int sig, u32 act, u32 old) -{ - u32 tmp, tmp2[4]; - struct sigaction s, s2; - int ret; - mm_segment_t old_fs = get_fs(); - struct sol_sigaction __user *p = (void __user *)A(old); - int (*sys_sigaction)(int,struct sigaction __user *,struct sigaction __user *) = - (int (*)(int,struct sigaction __user *,struct sigaction __user *))SYS(sigaction); - - sig = mapsig(sig); - if (sig < 0) { - /* We cheat a little bit for Solaris only signals */ - if (old && clear_user(p, sizeof(struct sol_sigaction))) - return -EFAULT; - return 0; - } - if (act) { - if (get_user (tmp, &p->sa_flags)) - return -EFAULT; - s.sa_flags = 0; - if (tmp & SOLARIS_SA_ONSTACK) s.sa_flags |= SA_STACK; - if (tmp & SOLARIS_SA_RESTART) s.sa_flags |= SA_RESTART; - if (tmp & SOLARIS_SA_NODEFER) s.sa_flags |= SA_NOMASK; - if (tmp & SOLARIS_SA_RESETHAND) s.sa_flags |= SA_ONESHOT; - if (tmp & SOLARIS_SA_NOCLDSTOP) s.sa_flags |= SA_NOCLDSTOP; - if (get_user (tmp, &p->sa_handler) || - copy_from_user (tmp2, &p->sa_mask, 2*sizeof(u32))) - return -EFAULT; - s.sa_handler = (__sighandler_t)A(tmp); - if (mapin (tmp2, &s.sa_mask)) return -EINVAL; - s.sa_restorer = NULL; - } - set_fs(KERNEL_DS); - ret = sys_sigaction(sig, act ? (void __user *)&s : NULL, - old ? (void __user *)&s2 : NULL); - set_fs(old_fs); - if (ret) return ret; - if (old) { - if (mapout (&s2.sa_mask, tmp2)) return -EINVAL; - tmp = 0; tmp2[2] = 0; tmp2[3] = 0; - if (s2.sa_flags & SA_STACK) tmp |= SOLARIS_SA_ONSTACK; - if (s2.sa_flags & SA_RESTART) tmp |= SOLARIS_SA_RESTART; - if (s2.sa_flags & SA_NOMASK) tmp |= SOLARIS_SA_NODEFER; - if (s2.sa_flags & SA_ONESHOT) tmp |= SOLARIS_SA_RESETHAND; - if (s2.sa_flags & SA_NOCLDSTOP) tmp |= SOLARIS_SA_NOCLDSTOP; - if (put_user (tmp, &p->sa_flags) || - __put_user ((u32)(unsigned long)s2.sa_handler, &p->sa_handler) || - copy_to_user (&p->sa_mask, tmp2, 4*sizeof(u32))) - return -EFAULT; - } - return 0; -} - -asmlinkage int solaris_sigpending(int which, u32 set) -{ - sigset_t s; - u32 tmp[4]; - switch (which) { - case 1: /* sigpending */ - spin_lock_irq(¤t->sighand->siglock); - sigandsets(&s, ¤t->blocked, ¤t->pending.signal); - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - break; - case 2: /* sigfillset - I just set signals which have linux equivalents */ - sigfillset(&s); - break; - default: return -EINVAL; - } - if (mapout (&s, tmp)) return -EINVAL; - tmp[2] = 0; tmp[3] = 0; - if (copy_to_user ((u32 __user *)A(set), tmp, sizeof(tmp))) - return -EFAULT; - return 0; -} - -asmlinkage int solaris_wait(u32 stat_loc) -{ - unsigned __user *p = (unsigned __user *)A(stat_loc); - int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) = - (int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4); - int ret, status; - - ret = sys_wait4(-1, p, WUNTRACED, NULL); - if (ret >= 0 && stat_loc) { - if (get_user (status, p)) - return -EFAULT; - if (((status - 1) & 0xffff) < 0xff) - status = linux_to_solaris_signals[status & 0x7f] & 0x7f; - else if ((status & 0xff) == 0x7f) - status = (linux_to_solaris_signals[(status >> 8) & 0xff] << 8) | 0x7f; - if (__put_user (status, p)) - return -EFAULT; - } - return ret; -} - -asmlinkage int solaris_waitid(int idtype, s32 pid, u32 info, int options) -{ - int (*sys_wait4)(pid_t,unsigned __user *, int, struct rusage __user *) = - (int (*)(pid_t,unsigned __user *, int, struct rusage __user *))SYS(wait4); - int opts, status, ret; - - switch (idtype) { - case 0: /* P_PID */ break; - case 1: /* P_PGID */ pid = -pid; break; - case 7: /* P_ALL */ pid = -1; break; - default: return -EINVAL; - } - opts = 0; - if (options & SOLARIS_WUNTRACED) opts |= WUNTRACED; - if (options & SOLARIS_WNOHANG) opts |= WNOHANG; - current->state = TASK_RUNNING; - ret = sys_wait4(pid, (unsigned int __user *)A(info), opts, NULL); - if (ret < 0) return ret; - if (info) { - struct sol_siginfo __user *s = (void __user *)A(info); - - if (get_user (status, (unsigned int __user *)A(info))) - return -EFAULT; - - if (__put_user (SOLARIS_SIGCLD, &s->si_signo) || - __put_user (ret, &s->_data._proc._pid)) - return -EFAULT; - - switch (status & 0xff) { - case 0: ret = SOLARIS_CLD_EXITED; - status = (status >> 8) & 0xff; - break; - case 0x7f: - status = (status >> 8) & 0xff; - switch (status) { - case SIGSTOP: - case SIGTSTP: ret = SOLARIS_CLD_STOPPED; - default: ret = SOLARIS_CLD_EXITED; - } - status = linux_to_solaris_signals[status]; - break; - default: - if (status & 0x80) ret = SOLARIS_CLD_DUMPED; - else ret = SOLARIS_CLD_KILLED; - status = linux_to_solaris_signals[status & 0x7f]; - break; - } - - if (__put_user (ret, &s->si_code) || - __put_user (status, &s->_data._proc._pdata._cld._status)) - return -EFAULT; - } - return 0; -} - -extern int svr4_setcontext(svr4_ucontext_t *c, struct pt_regs *regs); -extern int svr4_getcontext(svr4_ucontext_t *c, struct pt_regs *regs); - -asmlinkage int solaris_context(struct pt_regs *regs) -{ - switch ((unsigned)regs->u_regs[UREG_I0]) { - case 0: /* getcontext */ - return svr4_getcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs); - case 1: /* setcontext */ - return svr4_setcontext((svr4_ucontext_t *)(long)(u32)regs->u_regs[UREG_I1], regs); - default: - return -EINVAL; - - } -} - -asmlinkage int solaris_sigaltstack(u32 ss, u32 oss) -{ -/* XXX Implement this soon */ - return 0; -} diff --git a/arch/sparc64/solaris/signal.h b/arch/sparc64/solaris/signal.h deleted file mode 100644 index e91570803050..000000000000 --- a/arch/sparc64/solaris/signal.h +++ /dev/null @@ -1,108 +0,0 @@ -/* $Id: signal.h,v 1.3 1998/04/12 06:20:33 davem Exp $ - * signal.h: Signal emulation for Solaris - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - */ - -#define SOLARIS_SIGHUP 1 -#define SOLARIS_SIGINT 2 -#define SOLARIS_SIGQUIT 3 -#define SOLARIS_SIGILL 4 -#define SOLARIS_SIGTRAP 5 -#define SOLARIS_SIGIOT 6 -#define SOLARIS_SIGEMT 7 -#define SOLARIS_SIGFPE 8 -#define SOLARIS_SIGKILL 9 -#define SOLARIS_SIGBUS 10 -#define SOLARIS_SIGSEGV 11 -#define SOLARIS_SIGSYS 12 -#define SOLARIS_SIGPIPE 13 -#define SOLARIS_SIGALRM 14 -#define SOLARIS_SIGTERM 15 -#define SOLARIS_SIGUSR1 16 -#define SOLARIS_SIGUSR2 17 -#define SOLARIS_SIGCLD 18 -#define SOLARIS_SIGPWR 19 -#define SOLARIS_SIGWINCH 20 -#define SOLARIS_SIGURG 21 -#define SOLARIS_SIGPOLL 22 -#define SOLARIS_SIGSTOP 23 -#define SOLARIS_SIGTSTP 24 -#define SOLARIS_SIGCONT 25 -#define SOLARIS_SIGTTIN 26 -#define SOLARIS_SIGTTOU 27 -#define SOLARIS_SIGVTALRM 28 -#define SOLARIS_SIGPROF 29 -#define SOLARIS_SIGXCPU 30 -#define SOLARIS_SIGXFSZ 31 -#define SOLARIS_SIGWAITING 32 -#define SOLARIS_SIGLWP 33 -#define SOLARIS_SIGFREEZE 34 -#define SOLARIS_SIGTHAW 35 -#define SOLARIS_SIGCANCEL 36 -#define SOLARIS_SIGRTMIN 37 -#define SOLARIS_SIGRTMAX 44 -#define SOLARIS_NSIGNALS 44 - - -#define SOLARIS_SA_ONSTACK 1 -#define SOLARIS_SA_RESETHAND 2 -#define SOLARIS_SA_RESTART 4 -#define SOLARIS_SA_SIGINFO 8 -#define SOLARIS_SA_NODEFER 16 -#define SOLARIS_SA_NOCLDWAIT 0x10000 -#define SOLARIS_SA_NOCLDSTOP 0x20000 - -struct sol_siginfo { - int si_signo; - int si_code; - int si_errno; - union { - char pad[128-3*sizeof(int)]; - struct { - s32 _pid; - union { - struct { - s32 _uid; - s32 _value; - } _kill; - struct { - s32 _utime; - int _status; - s32 _stime; - } _cld; - } _pdata; - } _proc; - struct { /* SIGSEGV, SIGBUS, SIGILL and SIGFPE */ - u32 _addr; - int _trapno; - } _fault; - struct { /* SIGPOLL, SIGXFSZ */ - int _fd; - s32 _band; - } _file; - } _data; -}; - -#define SOLARIS_WUNTRACED 0x04 -#define SOLARIS_WNOHANG 0x40 -#define SOLARIS_WEXITED 0x01 -#define SOLARIS_WTRAPPED 0x02 -#define SOLARIS_WSTOPPED WUNTRACED -#define SOLARIS_WCONTINUED 0x08 -#define SOLARIS_WNOWAIT 0x80 - -#define SOLARIS_TRAP_BRKPT 1 -#define SOLARIS_TRAP_TRACE 2 -#define SOLARIS_CLD_EXITED 1 -#define SOLARIS_CLD_KILLED 2 -#define SOLARIS_CLD_DUMPED 3 -#define SOLARIS_CLD_TRAPPED 4 -#define SOLARIS_CLD_STOPPED 5 -#define SOLARIS_CLD_CONTINUED 6 -#define SOLARIS_POLL_IN 1 -#define SOLARIS_POLL_OUT 2 -#define SOLARIS_POLL_MSG 3 -#define SOLARIS_POLL_ERR 4 -#define SOLARIS_POLL_PRI 5 -#define SOLARIS_POLL_HUP 6 diff --git a/arch/sparc64/solaris/socket.c b/arch/sparc64/solaris/socket.c deleted file mode 100644 index cc69847cf240..000000000000 --- a/arch/sparc64/solaris/socket.c +++ /dev/null @@ -1,461 +0,0 @@ -/* $Id: socket.c,v 1.6 2002/02/08 03:57:14 davem Exp $ - * socket.c: Socket syscall emulation for Solaris 2.6+ - * - * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) - * - * 1999-08-19 Fixed socketpair code - * Jason Rappleye (rappleye@ccr.buffalo.edu) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include "conv.h" - -#define SOCK_SOL_STREAM 2 -#define SOCK_SOL_DGRAM 1 -#define SOCK_SOL_RAW 4 -#define SOCK_SOL_RDM 5 -#define SOCK_SOL_SEQPACKET 6 - -#define SOL_SO_SNDLOWAT 0x1003 -#define SOL_SO_RCVLOWAT 0x1004 -#define SOL_SO_SNDTIMEO 0x1005 -#define SOL_SO_RCVTIMEO 0x1006 -#define SOL_SO_STATE 0x2000 - -#define SOL_SS_NDELAY 0x040 -#define SOL_SS_NONBLOCK 0x080 -#define SOL_SS_ASYNC 0x100 - -#define SO_STATE 0x000e - -static int socket_check(int family, int type) -{ - if (family != PF_UNIX && family != PF_INET) - return -ESOCKTNOSUPPORT; - switch (type) { - case SOCK_SOL_STREAM: type = SOCK_STREAM; break; - case SOCK_SOL_DGRAM: type = SOCK_DGRAM; break; - case SOCK_SOL_RAW: type = SOCK_RAW; break; - case SOCK_SOL_RDM: type = SOCK_RDM; break; - case SOCK_SOL_SEQPACKET: type = SOCK_SEQPACKET; break; - default: return -EINVAL; - } - return type; -} - -static int solaris_to_linux_sockopt(int optname) -{ - switch (optname) { - case SOL_SO_SNDLOWAT: optname = SO_SNDLOWAT; break; - case SOL_SO_RCVLOWAT: optname = SO_RCVLOWAT; break; - case SOL_SO_SNDTIMEO: optname = SO_SNDTIMEO; break; - case SOL_SO_RCVTIMEO: optname = SO_RCVTIMEO; break; - case SOL_SO_STATE: optname = SO_STATE; break; - }; - - return optname; -} - -asmlinkage int solaris_socket(int family, int type, int protocol) -{ - int (*sys_socket)(int, int, int) = - (int (*)(int, int, int))SYS(socket); - - type = socket_check (family, type); - if (type < 0) return type; - return sys_socket(family, type, protocol); -} - -asmlinkage int solaris_socketpair(int *usockvec) -{ - int (*sys_socketpair)(int, int, int, int *) = - (int (*)(int, int, int, int *))SYS(socketpair); - - /* solaris socketpair really only takes one arg at the syscall - * level, int * usockvec. The libs apparently take care of - * making sure that family==AF_UNIX and type==SOCK_STREAM. The - * pointer we really want ends up residing in the first (and - * supposedly only) argument. - */ - - return sys_socketpair(AF_UNIX, SOCK_STREAM, 0, (int *)usockvec); -} - -asmlinkage int solaris_bind(int fd, struct sockaddr *addr, int addrlen) -{ - int (*sys_bind)(int, struct sockaddr *, int) = - (int (*)(int, struct sockaddr *, int))SUNOS(104); - - return sys_bind(fd, addr, addrlen); -} - -asmlinkage int solaris_setsockopt(int fd, int level, int optname, u32 optval, int optlen) -{ - int (*sunos_setsockopt)(int, int, int, u32, int) = - (int (*)(int, int, int, u32, int))SUNOS(105); - - optname = solaris_to_linux_sockopt(optname); - if (optname < 0) - return optname; - if (optname == SO_STATE) - return 0; - - return sunos_setsockopt(fd, level, optname, optval, optlen); -} - -asmlinkage int solaris_getsockopt(int fd, int level, int optname, u32 optval, u32 optlen) -{ - int (*sunos_getsockopt)(int, int, int, u32, u32) = - (int (*)(int, int, int, u32, u32))SUNOS(118); - - optname = solaris_to_linux_sockopt(optname); - if (optname < 0) - return optname; - - if (optname == SO_STATE) - optname = SOL_SO_STATE; - - return sunos_getsockopt(fd, level, optname, optval, optlen); -} - -asmlinkage int solaris_connect(int fd, struct sockaddr __user *addr, int addrlen) -{ - int (*sys_connect)(int, struct sockaddr __user *, int) = - (int (*)(int, struct sockaddr __user *, int))SYS(connect); - - return sys_connect(fd, addr, addrlen); -} - -asmlinkage int solaris_accept(int fd, struct sockaddr __user *addr, int __user *addrlen) -{ - int (*sys_accept)(int, struct sockaddr __user *, int __user *) = - (int (*)(int, struct sockaddr __user *, int __user *))SYS(accept); - - return sys_accept(fd, addr, addrlen); -} - -asmlinkage int solaris_listen(int fd, int backlog) -{ - int (*sys_listen)(int, int) = - (int (*)(int, int))SUNOS(106); - - return sys_listen(fd, backlog); -} - -asmlinkage int solaris_shutdown(int fd, int how) -{ - int (*sys_shutdown)(int, int) = - (int (*)(int, int))SYS(shutdown); - - return sys_shutdown(fd, how); -} - -#define MSG_SOL_OOB 0x1 -#define MSG_SOL_PEEK 0x2 -#define MSG_SOL_DONTROUTE 0x4 -#define MSG_SOL_EOR 0x8 -#define MSG_SOL_CTRUNC 0x10 -#define MSG_SOL_TRUNC 0x20 -#define MSG_SOL_WAITALL 0x40 -#define MSG_SOL_DONTWAIT 0x80 - -static int solaris_to_linux_msgflags(int flags) -{ - int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE); - - if (flags & MSG_SOL_EOR) fl |= MSG_EOR; - if (flags & MSG_SOL_CTRUNC) fl |= MSG_CTRUNC; - if (flags & MSG_SOL_TRUNC) fl |= MSG_TRUNC; - if (flags & MSG_SOL_WAITALL) fl |= MSG_WAITALL; - if (flags & MSG_SOL_DONTWAIT) fl |= MSG_DONTWAIT; - return fl; -} - -static int linux_to_solaris_msgflags(int flags) -{ - int fl = flags & (MSG_OOB|MSG_PEEK|MSG_DONTROUTE); - - if (flags & MSG_EOR) fl |= MSG_SOL_EOR; - if (flags & MSG_CTRUNC) fl |= MSG_SOL_CTRUNC; - if (flags & MSG_TRUNC) fl |= MSG_SOL_TRUNC; - if (flags & MSG_WAITALL) fl |= MSG_SOL_WAITALL; - if (flags & MSG_DONTWAIT) fl |= MSG_SOL_DONTWAIT; - return fl; -} - -asmlinkage int solaris_recvfrom(int s, char __user *buf, int len, int flags, u32 from, u32 fromlen) -{ - int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) = - (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom); - - return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), A(from), A(fromlen)); -} - -asmlinkage int solaris_recv(int s, char __user *buf, int len, int flags) -{ - int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) = - (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom); - - return sys_recvfrom(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL); -} - -asmlinkage int solaris_sendto(int s, char __user *buf, int len, int flags, u32 to, u32 tolen) -{ - int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *) = - (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(sendto); - - return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), A(to), A(tolen)); -} - -asmlinkage int solaris_send(int s, char *buf, int len, int flags) -{ - int (*sys_sendto)(int, void *, size_t, unsigned, struct sockaddr *, int *) = - (int (*)(int, void *, size_t, unsigned, struct sockaddr *, int *))SYS(sendto); - - return sys_sendto(s, buf, len, solaris_to_linux_msgflags(flags), NULL, NULL); -} - -asmlinkage int solaris_getpeername(int fd, struct sockaddr *addr, int *addrlen) -{ - int (*sys_getpeername)(int, struct sockaddr *, int *) = - (int (*)(int, struct sockaddr *, int *))SYS(getpeername); - - return sys_getpeername(fd, addr, addrlen); -} - -asmlinkage int solaris_getsockname(int fd, struct sockaddr *addr, int *addrlen) -{ - int (*sys_getsockname)(int, struct sockaddr *, int *) = - (int (*)(int, struct sockaddr *, int *))SYS(getsockname); - - return sys_getsockname(fd, addr, addrlen); -} - -/* XXX This really belongs in some header file... -DaveM */ -#define MAX_SOCK_ADDR 128 /* 108 for Unix domain - - 16 for IP, 16 for IPX, - 24 for IPv6, - about 80 for AX.25 */ - -struct sol_nmsghdr { - u32 msg_name; - int msg_namelen; - u32 msg_iov; - u32 msg_iovlen; - u32 msg_control; - u32 msg_controllen; - u32 msg_flags; -}; - -struct sol_cmsghdr { - u32 cmsg_len; - int cmsg_level; - int cmsg_type; - unsigned char cmsg_data[0]; -}; - -static inline int msghdr_from_user32_to_kern(struct msghdr *kmsg, - struct sol_nmsghdr __user *umsg) -{ - u32 tmp1, tmp2, tmp3; - int err; - - err = get_user(tmp1, &umsg->msg_name); - err |= __get_user(tmp2, &umsg->msg_iov); - err |= __get_user(tmp3, &umsg->msg_control); - if (err) - return -EFAULT; - - kmsg->msg_name = A(tmp1); - kmsg->msg_iov = A(tmp2); - kmsg->msg_control = A(tmp3); - - err = get_user(kmsg->msg_namelen, &umsg->msg_namelen); - err |= get_user(kmsg->msg_controllen, &umsg->msg_controllen); - err |= get_user(kmsg->msg_flags, &umsg->msg_flags); - - kmsg->msg_flags = solaris_to_linux_msgflags(kmsg->msg_flags); - - return err; -} - -asmlinkage int solaris_sendmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned user_flags) -{ - struct socket *sock; - char address[MAX_SOCK_ADDR]; - struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; - unsigned char ctl[sizeof(struct cmsghdr) + 20]; - unsigned char *ctl_buf = ctl; - struct msghdr msg_sys; - int err, ctl_len, iov_size, total_len; - - err = -EFAULT; - if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) - goto out; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - /* do not move before msg_sys is valid */ - err = -EMSGSIZE; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - err = verify_compat_iovec(&msg_sys, iov, address, VERIFY_READ); - if (err < 0) - goto out_freeiov; - total_len = err; - - err = -ENOBUFS; - if (msg_sys.msg_controllen > INT_MAX) - goto out_freeiov; - - ctl_len = msg_sys.msg_controllen; - if (ctl_len) { - struct sol_cmsghdr __user *ucmsg = msg_sys.msg_control; - unsigned long *kcmsg; - compat_size_t cmlen; - - err = -EINVAL; - if (ctl_len <= sizeof(compat_size_t)) - goto out_freeiov; - - if (ctl_len > sizeof(ctl)) { - err = -ENOBUFS; - ctl_buf = kmalloc(ctl_len, GFP_KERNEL); - if (!ctl_buf) - goto out_freeiov; - } - __get_user(cmlen, &ucmsg->cmsg_len); - kcmsg = (unsigned long *) ctl_buf; - *kcmsg++ = (unsigned long)cmlen; - err = -EFAULT; - if (copy_from_user(kcmsg, &ucmsg->cmsg_level, - ctl_len - sizeof(compat_size_t))) - goto out_freectl; - msg_sys.msg_control = ctl_buf; - } - msg_sys.msg_flags = solaris_to_linux_msgflags(user_flags); - - if (sock->file->f_flags & O_NONBLOCK) - msg_sys.msg_flags |= MSG_DONTWAIT; - err = sock_sendmsg(sock, &msg_sys, total_len); - -out_freectl: - if (ctl_buf != ctl) - sock_kfree_s(sock->sk, ctl_buf, ctl_len); -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} - -asmlinkage int solaris_recvmsg(int fd, struct sol_nmsghdr __user *user_msg, unsigned int user_flags) -{ - struct socket *sock; - struct iovec iovstack[UIO_FASTIOV]; - struct iovec *iov = iovstack; - struct msghdr msg_sys; - unsigned long cmsg_ptr; - int err, iov_size, total_len, len; - - /* kernel mode address */ - char addr[MAX_SOCK_ADDR]; - - /* user mode address pointers */ - struct sockaddr __user *uaddr; - int __user *uaddr_len; - - if (msghdr_from_user32_to_kern(&msg_sys, user_msg)) - return -EFAULT; - - sock = sockfd_lookup(fd, &err); - if (!sock) - goto out; - - err = -EMSGSIZE; - if (msg_sys.msg_iovlen > UIO_MAXIOV) - goto out_put; - - /* Check whether to allocate the iovec area*/ - err = -ENOMEM; - iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); - if (msg_sys.msg_iovlen > UIO_FASTIOV) { - iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); - if (!iov) - goto out_put; - } - - /* - * Save the user-mode address (verify_iovec will change the - * kernel msghdr to use the kernel address space) - */ - - uaddr = (void __user *) msg_sys.msg_name; - uaddr_len = &user_msg->msg_namelen; - err = verify_compat_iovec(&msg_sys, iov, addr, VERIFY_WRITE); - if (err < 0) - goto out_freeiov; - total_len = err; - - cmsg_ptr = (unsigned long) msg_sys.msg_control; - msg_sys.msg_flags = MSG_CMSG_COMPAT; - - if (sock->file->f_flags & O_NONBLOCK) - user_flags |= MSG_DONTWAIT; - - err = sock_recvmsg(sock, &msg_sys, total_len, user_flags); - if(err < 0) - goto out_freeiov; - - len = err; - - if (uaddr != NULL) { - err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len); - if (err < 0) - goto out_freeiov; - } - err = __put_user(linux_to_solaris_msgflags(msg_sys.msg_flags), &user_msg->msg_flags); - if (err) - goto out_freeiov; - err = __put_user((unsigned long)msg_sys.msg_control - cmsg_ptr, - &user_msg->msg_controllen); - if (err) - goto out_freeiov; - err = len; - -out_freeiov: - if (iov != iovstack) - sock_kfree_s(sock->sk, iov, iov_size); -out_put: - sockfd_put(sock); -out: - return err; -} diff --git a/arch/sparc64/solaris/socksys.c b/arch/sparc64/solaris/socksys.c deleted file mode 100644 index 7736411f244f..000000000000 --- a/arch/sparc64/solaris/socksys.c +++ /dev/null @@ -1,203 +0,0 @@ -/* $Id: socksys.c,v 1.21 2002/02/08 03:57:14 davem Exp $ - * socksys.c: /dev/inet/ stuff for Solaris emulation. - * - * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1997, 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) - * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) - */ - -/* - * Dave, _please_ give me specifications on this fscking mess so that I - * could at least get it into the state when it wouldn't screw the rest of - * the kernel over. socksys.c and timod.c _stink_ and we are not talking - * H2S here, it's isopropilmercaptan in concentrations way over LD50. -- AV - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "conv.h" -#include "socksys.h" - -static int af_inet_protocols[] = { -IPPROTO_ICMP, IPPROTO_ICMP, IPPROTO_IGMP, IPPROTO_IPIP, IPPROTO_TCP, -IPPROTO_EGP, IPPROTO_PUP, IPPROTO_UDP, IPPROTO_IDP, IPPROTO_RAW, -0, 0, 0, 0, 0, 0, -}; - -#ifndef DEBUG_SOLARIS_KMALLOC - -#define mykmalloc kmalloc -#define mykfree kfree - -#else - -extern void * mykmalloc(size_t s, gfp_t gfp); -extern void mykfree(void *); - -#endif - -static unsigned int (*sock_poll)(struct file *, poll_table *); - -static struct file_operations socksys_file_ops = { - /* Currently empty */ -}; - -static int socksys_open(struct inode * inode, struct file * filp) -{ - int family, type, protocol, fd; - struct dentry *dentry; - int (*sys_socket)(int,int,int) = - (int (*)(int,int,int))SUNOS(97); - struct sol_socket_struct * sock; - - family = ((iminor(inode) >> 4) & 0xf); - switch (family) { - case AF_UNIX: - type = SOCK_STREAM; - protocol = 0; - break; - case AF_INET: - protocol = af_inet_protocols[iminor(inode) & 0xf]; - switch (protocol) { - case IPPROTO_TCP: type = SOCK_STREAM; break; - case IPPROTO_UDP: type = SOCK_DGRAM; break; - default: type = SOCK_RAW; break; - } - break; - default: - type = SOCK_RAW; - protocol = 0; - break; - } - - fd = sys_socket(family, type, protocol); - if (fd < 0) - return fd; - /* - * N.B. The following operations are not legal! - * - * No shit. WTF is it supposed to do, anyway? - * - * Try instead: - * d_delete(filp->f_path.dentry), then d_instantiate with sock inode - */ - dentry = filp->f_path.dentry; - filp->f_path.dentry = dget(fcheck(fd)->f_path.dentry); - filp->f_path.dentry->d_inode->i_rdev = inode->i_rdev; - filp->f_path.dentry->d_inode->i_flock = inode->i_flock; - SOCKET_I(filp->f_path.dentry->d_inode)->file = filp; - filp->f_op = &socksys_file_ops; - sock = (struct sol_socket_struct*) - mykmalloc(sizeof(struct sol_socket_struct), GFP_KERNEL); - if (!sock) return -ENOMEM; - SOLDD(("sock=%016lx(%016lx)\n", sock, filp)); - sock->magic = SOLARIS_SOCKET_MAGIC; - sock->modcount = 0; - sock->state = TS_UNBND; - sock->offset = 0; - sock->pfirst = sock->plast = NULL; - filp->private_data = sock; - SOLDD(("filp->private_data %016lx\n", filp->private_data)); - - sys_close(fd); - dput(dentry); - return 0; -} - -static int socksys_release(struct inode * inode, struct file * filp) -{ - struct sol_socket_struct * sock; - struct T_primsg *it; - - /* XXX: check this */ - sock = (struct sol_socket_struct *)filp->private_data; - SOLDD(("sock release %016lx(%016lx)\n", sock, filp)); - it = sock->pfirst; - while (it) { - struct T_primsg *next = it->next; - - SOLDD(("socksys_release %016lx->%016lx\n", it, next)); - mykfree((char*)it); - it = next; - } - filp->private_data = NULL; - SOLDD(("socksys_release %016lx\n", sock)); - mykfree((char*)sock); - return 0; -} - -static unsigned int socksys_poll(struct file * filp, poll_table * wait) -{ - struct inode *ino; - unsigned int mask = 0; - - ino=filp->f_path.dentry->d_inode; - if (ino && S_ISSOCK(ino->i_mode)) { - struct sol_socket_struct *sock; - sock = (struct sol_socket_struct*)filp->private_data; - if (sock && sock->pfirst) { - mask |= POLLIN | POLLRDNORM; - if (sock->pfirst->pri == MSG_HIPRI) - mask |= POLLPRI; - } - } - if (sock_poll) - mask |= (*sock_poll)(filp, wait); - return mask; -} - -static const struct file_operations socksys_fops = { - .open = socksys_open, - .release = socksys_release, -}; - -int __init init_socksys(void) -{ - int ret; - struct file * file; - int (*sys_socket)(int,int,int) = - (int (*)(int,int,int))SUNOS(97); - int (*sys_close)(unsigned int) = - (int (*)(unsigned int))SYS(close); - - ret = register_chrdev (30, "socksys", &socksys_fops); - if (ret < 0) { - printk ("Couldn't register socksys character device\n"); - return ret; - } - ret = sys_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); - if (ret < 0) { - printk ("Couldn't create socket\n"); - return ret; - } - - file = fcheck(ret); - /* N.B. Is this valid? Suppose the f_ops are in a module ... */ - socksys_file_ops = *file->f_op; - sys_close(ret); - sock_poll = socksys_file_ops.poll; - socksys_file_ops.poll = socksys_poll; - socksys_file_ops.release = socksys_release; - return 0; -} - -void __exit cleanup_socksys(void) -{ - unregister_chrdev(30, "socksys"); -} diff --git a/arch/sparc64/solaris/socksys.h b/arch/sparc64/solaris/socksys.h deleted file mode 100644 index 5d1b78ec1600..000000000000 --- a/arch/sparc64/solaris/socksys.h +++ /dev/null @@ -1,208 +0,0 @@ -/* $Id: socksys.h,v 1.2 1998/03/26 08:46:07 jj Exp $ - * socksys.h: Definitions for STREAMS modules emulation code. - * - * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) - */ - -#define MSG_HIPRI 0x01 -#define MSG_ANY 0x02 -#define MSG_BAND 0x04 - -#define MORECTL 1 -#define MOREDATA 2 - -#define TBADADDR 1 -#define TBADOPT 2 -#define TACCES 3 -#define TBADF 4 -#define TNOADDR 5 -#define TOUTSTATE 6 -#define TBADSEQ 7 -#define TSYSERR 8 -#define TLOOK 9 -#define TBADDATA 10 -#define TBUFOVFLW 11 -#define TFLOW 12 -#define TNODATA 13 -#define TNODIS 14 -#define TNOUDERR 15 -#define TBADFLAG 16 -#define TNOREL 17 -#define TNOTSUPPORT 18 -#define TSTATECHNG 19 - -#define T_CONN_REQ 0 -#define T_CONN_RES 1 -#define T_DISCON_REQ 2 -#define T_DATA_REQ 3 -#define T_EXDATA_REQ 4 -#define T_INFO_REQ 5 -#define T_BIND_REQ 6 -#define T_UNBIND_REQ 7 -#define T_UNITDATA_REQ 8 -#define T_OPTMGMT_REQ 9 -#define T_ORDREL_REQ 10 - -#define T_CONN_IND 11 -#define T_CONN_CON 12 -#define T_DISCON_IND 13 -#define T_DATA_IND 14 -#define T_EXDATA_IND 15 -#define T_INFO_ACK 16 -#define T_BIND_ACK 17 -#define T_ERROR_ACK 18 -#define T_OK_ACK 19 -#define T_UNITDATA_IND 20 -#define T_UDERROR_IND 21 -#define T_OPTMGMT_ACK 22 -#define T_ORDREL_IND 23 - -#define T_NEGOTIATE 0x0004 -#define T_FAILURE 0x0040 - -#define TS_UNBND 0 /* unbound */ -#define TS_WACK_BREQ 1 /* waiting for T_BIND_REQ ack */ -#define TS_WACK_UREQ 2 /* waiting for T_UNBIND_REQ ack */ -#define TS_IDLE 3 /* idle */ -#define TS_WACK_OPTREQ 4 /* waiting for T_OPTMGMT_REQ ack */ -#define TS_WACK_CREQ 5 /* waiting for T_CONN_REQ ack */ -#define TS_WCON_CREQ 6 /* waiting for T_CONN_REQ confirmation */ -#define TS_WRES_CIND 7 /* waiting for T_CONN_IND */ -#define TS_WACK_CRES 8 /* waiting for T_CONN_RES ack */ -#define TS_DATA_XFER 9 /* data transfer */ -#define TS_WIND_ORDREL 10 /* releasing read but not write */ -#define TS_WREQ_ORDREL 11 /* wait to release write but not read */ -#define TS_WACK_DREQ6 12 /* waiting for T_DISCON_REQ ack */ -#define TS_WACK_DREQ7 13 /* waiting for T_DISCON_REQ ack */ -#define TS_WACK_DREQ9 14 /* waiting for T_DISCON_REQ ack */ -#define TS_WACK_DREQ10 15 /* waiting for T_DISCON_REQ ack */ -#define TS_WACK_DREQ11 16 /* waiting for T_DISCON_REQ ack */ -#define TS_NOSTATES 17 - -struct T_conn_req { - s32 PRIM_type; - s32 DEST_length; - s32 DEST_offset; - s32 OPT_length; - s32 OPT_offset; -}; - -struct T_bind_req { - s32 PRIM_type; - s32 ADDR_length; - s32 ADDR_offset; - u32 CONIND_number; -}; - -struct T_unitdata_req { - s32 PRIM_type; - s32 DEST_length; - s32 DEST_offset; - s32 OPT_length; - s32 OPT_offset; -}; - -struct T_optmgmt_req { - s32 PRIM_type; - s32 OPT_length; - s32 OPT_offset; - s32 MGMT_flags; -}; - -struct T_bind_ack { - s32 PRIM_type; - s32 ADDR_length; - s32 ADDR_offset; - u32 CONIND_number; -}; - -struct T_error_ack { - s32 PRIM_type; - s32 ERROR_prim; - s32 TLI_error; - s32 UNIX_error; -}; - -struct T_ok_ack { - s32 PRIM_type; - s32 CORRECT_prim; -}; - -struct T_conn_ind { - s32 PRIM_type; - s32 SRC_length; - s32 SRC_offset; - s32 OPT_length; - s32 OPT_offset; - s32 SEQ_number; -}; - -struct T_conn_con { - s32 PRIM_type; - s32 RES_length; - s32 RES_offset; - s32 OPT_length; - s32 OPT_offset; -}; - -struct T_discon_ind { - s32 PRIM_type; - s32 DISCON_reason; - s32 SEQ_number; -}; - -struct T_unitdata_ind { - s32 PRIM_type; - s32 SRC_length; - s32 SRC_offset; - s32 OPT_length; - s32 OPT_offset; -}; - -struct T_optmgmt_ack { - s32 PRIM_type; - s32 OPT_length; - s32 OPT_offset; - s32 MGMT_flags; -}; - -struct opthdr { - s32 level; - s32 name; - s32 len; - char value[0]; -}; - -struct T_primsg { - struct T_primsg *next; - unsigned char pri; - unsigned char band; - int length; - s32 type; -}; - -struct strbuf { - s32 maxlen; - s32 len; - u32 buf; -} ; - -/* Constants used by STREAMS modules emulation code */ - -typedef char sol_module; - -#define MAX_NR_STREAM_MODULES 16 - -/* Private data structure assigned to sockets. */ - -struct sol_socket_struct { - int magic; - int modcount; - sol_module module[MAX_NR_STREAM_MODULES]; - long state; - int offset; - struct T_primsg *pfirst, *plast; -}; - -#define SOLARIS_SOCKET_MAGIC 0xADDED - diff --git a/arch/sparc64/solaris/systbl.S b/arch/sparc64/solaris/systbl.S deleted file mode 100644 index 7043ca18caf9..000000000000 --- a/arch/sparc64/solaris/systbl.S +++ /dev/null @@ -1,285 +0,0 @@ -/* $Id: systbl.S,v 1.11 2000/03/13 21:57:35 davem Exp $ - * systbl.S: System call entry point table for Solaris compatibility. - * - * Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) - * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) - */ - -#include - -/* Fall back to sys_call_table32 entry */ -#define CHAIN(name) __NR_##name - -/* Pass pt_regs pointer as first argument */ -#define REGS(name) name+1 - -/* Hack till all be implemented */ -#define solaris_getpmsg solaris_unimplemented -#define solaris_hrtsys solaris_unimplemented -#define solaris_msgsys solaris_unimplemented -#define solaris_putpmsg solaris_unimplemented -#define solaris_semsys solaris_unimplemented - - .data - .globl solaris_sys_table -solaris_sys_table: - .word solaris_unimplemented /* nosys 0 */ - .word CHAIN(exit) /* exit d 1 */ - .word CHAIN(fork) /* fork 2 */ - .word CHAIN(read) /* read dpd 3 */ - .word CHAIN(write) /* write dpd 4 */ - .word solaris_open /* open soo 5 */ - .word CHAIN(close) /* close d 6 */ - .word solaris_wait /* wait xxx 7 */ - .word CHAIN(creat) /* creat so 8 */ - .word CHAIN(link) /* link ss 9 */ - .word CHAIN(unlink) /* unlink s 10 */ - .word solaris_unimplemented /* exec sxx 11 */ - .word CHAIN(chdir) /* chdir s 12 */ - .word CHAIN(time) /* time 13 */ - .word solaris_mknod /* mknod sox 14 */ - .word CHAIN(chmod) /* chmod so 15 */ - .word CHAIN(chown) /* chown sdd 16 */ - .word solaris_brk /* brk/break x 17 */ - .word solaris_stat /* stat sp 18 */ - .word CHAIN(lseek) /* seek/lseek ddd 19 */ - .word solaris_getpid /* getpid 20 */ - .word solaris_unimplemented /* mount 21 */ - .word CHAIN(umount) /* umount s 22 */ - .word CHAIN(setuid) /* setuid d 23 */ - .word solaris_getuid /* getuid 24 */ - .word CHAIN(stime) /* stime d 25 */ -#if 0 - .word solaris_ptrace /* ptrace xdxx 26 */ -#else - .word CHAIN(ptrace) /* ptrace xdxx 26 */ -#endif - .word CHAIN(alarm) /* alarm d 27 */ - .word solaris_fstat /* fstat dp 28 */ - .word CHAIN(pause) /* pause 29 */ - .word CHAIN(utime) /* utime xx 30 */ - .word solaris_unimplemented /* stty 31 */ - .word solaris_unimplemented /* gtty 32 */ - .word solaris_access /* access so 33 */ - .word CHAIN(nice) /* nice d 34 */ - .word solaris_statfs /* statfs spdd 35 */ - .word CHAIN(sync) /* sync 36 */ - .word solaris_kill /* kill dd 37 */ - .word solaris_fstatfs /* fstatfs dpdd 38 */ - .word solaris_procids /* pgrpsys ddd 39 */ - .word solaris_unimplemented /* xenix 40 */ - .word CHAIN(dup) /* dup d 41 */ - .word CHAIN(pipe) /* pipe 42 */ - .word CHAIN(times) /* times p 43 */ - .word 44 /*CHAIN(profil)*/ /* prof xxxx 44 */ - .word solaris_unimplemented /* lock/plock 45 */ - .word CHAIN(setgid) /* setgid d 46 */ - .word solaris_getgid /* getgid 47 */ - .word solaris_sigfunc /* sigfunc xx 48 */ - .word REGS(solaris_msgsys) /* msgsys dxddd 49 */ - .word solaris_unimplemented /* syssun/3b 50 */ - .word CHAIN(acct) /* acct/sysacct x 51 */ - .word solaris_shmsys /* shmsys ddxo 52 */ - .word REGS(solaris_semsys) /* semsys dddx 53 */ - .word solaris_ioctl /* ioctl dxx 54 */ - .word solaris_unimplemented /* uadmin xxx 55 */ - .word solaris_unimplemented /* reserved:exch 56 */ - .word solaris_utssys /* utssys x 57 */ - .word CHAIN(fsync) /* fsync d 58 */ - .word CHAIN(execve) /* execv spp 59 */ - .word CHAIN(umask) /* umask o 60 */ - .word CHAIN(chroot) /* chroot s 61 */ - .word solaris_fcntl /* fcntl dxx 62 */ - .word solaris_ulimit /* ulimit xx 63 */ - .word solaris_unimplemented /* ? 64 */ - .word solaris_unimplemented /* ? 65 */ - .word solaris_unimplemented /* ? 66 */ - .word solaris_unimplemented /* ? 67 */ - .word solaris_unimplemented /* ? 68 */ - .word solaris_unimplemented /* ? 69 */ - .word solaris_unimplemented /* advfs 70 */ - .word solaris_unimplemented /* unadvfs 71 */ - .word solaris_unimplemented /* rmount 72 */ - .word solaris_unimplemented /* rumount 73 */ - .word solaris_unimplemented /* rfstart 74 */ - .word solaris_unimplemented /* ? 75 */ - .word solaris_unimplemented /* rdebug 76 */ - .word solaris_unimplemented /* rfstop 77 */ - .word solaris_unimplemented /* rfsys 78 */ - .word CHAIN(rmdir) /* rmdir s 79 */ - .word CHAIN(mkdir) /* mkdir so 80 */ - .word CHAIN(getdents) /* getdents dxd 81 */ - .word solaris_unimplemented /* libattach 82 */ - .word solaris_unimplemented /* libdetach 83 */ - .word CHAIN(sysfs) /* sysfs dxx 84 */ - .word solaris_getmsg /* getmsg dxxx 85 */ - .word solaris_putmsg /* putmsg dxxd 86 */ - .word CHAIN(poll) /* poll xdd 87 */ - .word solaris_lstat /* lstat sp 88 */ - .word CHAIN(symlink) /* symlink ss 89 */ - .word CHAIN(readlink) /* readlink spd 90 */ - .word CHAIN(setgroups) /* setgroups dp 91 */ - .word CHAIN(getgroups) /* getgroups dp 92 */ - .word CHAIN(fchmod) /* fchmod do 93 */ - .word CHAIN(fchown) /* fchown ddd 94 */ - .word solaris_sigprocmask /* sigprocmask dxx 95 */ - .word solaris_sigsuspend /* sigsuspend x 96 */ - .word solaris_sigaltstack /* sigaltstack xx 97 */ - .word solaris_sigaction /* sigaction dxx 98 */ - .word solaris_sigpending /* sigpending dd 99 */ - .word REGS(solaris_context) /* context 100 */ - .word solaris_unimplemented /* evsys 101 */ - .word solaris_unimplemented /* evtrapret 102 */ - .word solaris_statvfs /* statvfs sp 103 */ - .word solaris_fstatvfs /* fstatvfs dp 104 */ - .word solaris_unimplemented /* unknown 105 */ - .word solaris_unimplemented /* nfssys 106 */ - .word solaris_waitid /* waitid ddxd 107 */ - .word solaris_unimplemented /* sigsendsys ddd 108 */ - .word REGS(solaris_hrtsys) /* hrtsys xxx 109 */ - .word solaris_unimplemented /* acancel dxd 110 */ - .word solaris_unimplemented /* async 111 */ - .word solaris_unimplemented /* priocntlsys 112 */ - .word solaris_pathconf /* pathconf sd 113 */ - .word CHAIN(mincore) /* mincore d 114 */ - .word solaris_mmap /* mmap xxxxdx 115 */ - .word CHAIN(mprotect) /* mprotect xdx 116 */ - .word CHAIN(munmap) /* munmap xd 117 */ - .word solaris_fpathconf /* fpathconf dd 118 */ - .word CHAIN(fork) /* fork 119 */ - .word solaris_unimplemented /* fchdir d 120 */ - .word CHAIN(readv) /* readv dxd 121 */ - .word CHAIN(writev) /* writev dxd 122 */ - .word solaris_xstat /* xstat dsx 123 */ - .word solaris_lxstat /* lxstat dsx 124 */ - .word solaris_fxstat /* fxstat ddx 125 */ - .word solaris_xmknod /* xmknod dsox 126 */ - .word solaris_unimplemented /* syslocal d 127 */ - .word solaris_setrlimit /* setrlimit dp 128 */ - .word solaris_getrlimit /* getrlimit dp 129 */ - .word CHAIN(chown) /* lchown sdd 130 */ - .word solaris_unimplemented /* memcntl 131 */ - .word solaris_getpmsg /* getpmsg dxxxx 132 */ - .word solaris_putpmsg /* putpmsg dxxdd 133 */ - .word CHAIN(rename) /* rename ss 134 */ - .word solaris_utsname /* uname x 135 */ - .word solaris_unimplemented /* setegid 136 */ - .word solaris_sysconf /* sysconfig d 137 */ - .word solaris_unimplemented /* adjtime 138 */ - .word solaris_sysinfo /* systeminfo dsd 139 */ - .word solaris_unimplemented /* ? 140 */ - .word solaris_unimplemented /* seteuid 141 */ - .word solaris_unimplemented /* ? 142 */ - .word solaris_unimplemented /* ? 143 */ - .word solaris_unimplemented /* secsys dx 144 */ - .word solaris_unimplemented /* filepriv sdxd 145 */ - .word solaris_unimplemented /* procpriv dxd 146 */ - .word solaris_unimplemented /* devstat sdx 147 */ - .word solaris_unimplemented /* aclipc ddddx 148 */ - .word solaris_unimplemented /* fdevstat ddx 149 */ - .word solaris_unimplemented /* flvlfile ddx 150 */ - .word solaris_unimplemented /* lvlfile sdx 151 */ - .word solaris_unimplemented /* ? 152 */ - .word solaris_unimplemented /* fchroot d 153 */ - .word solaris_unimplemented /* lvlproc dx 154 */ - .word solaris_unimplemented /* ? 155 */ - .word solaris_gettimeofday /* gettimeofday x 156 */ - .word CHAIN(getitimer) /* getitimer dx 157 */ - .word CHAIN(setitimer) /* setitimer dxx 158 */ - .word solaris_unimplemented /* lwp-xxx 159 */ - .word solaris_unimplemented /* lwp-xxx 160 */ - .word solaris_unimplemented /* lwp-xxx 161 */ - .word solaris_unimplemented /* lwp-xxx 162 */ - .word solaris_unimplemented /* lwp-xxx 163 */ - .word solaris_unimplemented /* lwp-xxx 164 */ - .word solaris_unimplemented /* lwp-xxx 165 */ - .word solaris_unimplemented /* lwp-xxx 166 */ - .word solaris_unimplemented /* lwp-xxx 167 */ - .word solaris_unimplemented /* lwp-xxx 168 */ - .word solaris_unimplemented /* lwp-xxx 169 */ - .word solaris_unimplemented /* lwp-xxx 170 */ - .word solaris_unimplemented /* lwp-xxx 171 */ - .word solaris_unimplemented /* lwp-xxx 172 */ - .word solaris_pread /* pread dpdd 173 */ - .word solaris_pwrite /* pwrite dpdd 174 */ - .word REGS(solaris_llseek) /* llseek dLd 175 */ - .word solaris_unimplemented /* lwpself 176 */ - .word solaris_unimplemented /* lwpinfo 177 */ - .word solaris_unimplemented /* lwpprivate 178 */ - .word solaris_unimplemented /* processorbind 179 */ - .word solaris_unimplemented /* processorexbind 180 */ - .word solaris_unimplemented /* 181 */ - .word solaris_unimplemented /* sync_mailbox 182 */ - .word solaris_unimplemented /* prepblock 183 */ - .word solaris_unimplemented /* block 184 */ - .word solaris_acl /* acl sddp 185 */ - .word solaris_unimplemented /* unblock 186 */ - .word solaris_unimplemented /* cancelblock 187 */ - .word solaris_unimplemented /* ? 188 */ - .word solaris_unimplemented /* xxxxx 189 */ - .word solaris_unimplemented /* xxxxxe 190 */ - .word solaris_unimplemented /* 191 */ - .word solaris_unimplemented /* 192 */ - .word solaris_unimplemented /* 193 */ - .word solaris_unimplemented /* 194 */ - .word solaris_unimplemented /* 195 */ - .word solaris_unimplemented /* 196 */ - .word solaris_unimplemented /* 197 */ - .word solaris_unimplemented /* 198 */ - .word CHAIN(nanosleep) /* nanosleep dd 199 */ - .word solaris_facl /* facl dddp 200 */ - .word solaris_unimplemented /* 201 */ - .word CHAIN(setreuid) /* setreuid dd 202 */ - .word CHAIN(setregid) /* setregid dd 203 */ - .word solaris_unimplemented /* 204 */ - .word solaris_unimplemented /* 205 */ - .word solaris_unimplemented /* 206 */ - .word solaris_unimplemented /* 207 */ - .word solaris_unimplemented /* 208 */ - .word solaris_unimplemented /* 209 */ - .word solaris_unimplemented /* 210 */ - .word solaris_unimplemented /* 211 */ - .word solaris_unimplemented /* 212 */ - .word solaris_getdents64 /* getdents64 dpd 213 */ - .word REGS(solaris_mmap64) /* mmap64 xxxxdX 214 */ - .word solaris_stat64 /* stat64 sP 215 */ - .word solaris_lstat64 /* lstat64 sP 216 */ - .word solaris_fstat64 /* fstat64 dP 217 */ - .word solaris_statvfs64 /* statvfs64 sP 218 */ - .word solaris_fstatvfs64 /* fstatvfs64 dP 219 */ - .word solaris_setrlimit64 /* setrlimit64 dP 220 */ - .word solaris_getrlimit64 /* getrlimit64 dP 221 */ - .word CHAIN(pread64) /* pread64 dpdD 222 */ - .word CHAIN(pwrite64) /* pwrite64 dpdD 223 */ - .word CHAIN(creat) /* creat64 so 224 */ - .word solaris_open /* open64 soo 225 */ - .word solaris_unimplemented /* 226 */ - .word solaris_unimplemented /* 227 */ - .word solaris_unimplemented /* 228 */ - .word solaris_unimplemented /* 229 */ - .word solaris_socket /* socket ddd 230 */ - .word solaris_socketpair /* socketpair dddp 231 */ - .word solaris_bind /* bind dpd 232 */ - .word solaris_listen /* listen dd 233 */ - .word solaris_accept /* accept dpp 234 */ - .word solaris_connect /* connect dpd 235 */ - .word solaris_shutdown /* shutdown dd 236 */ - .word solaris_recv /* recv dpdd 237 */ - .word solaris_recvfrom /* recvfrom dpddpp 238 */ - .word solaris_recvmsg /* recvmsg dpd 239 */ - .word solaris_send /* send dpdd 240 */ - .word solaris_sendmsg /* sendmsg dpd 241 */ - .word solaris_sendto /* sendto dpddpd 242 */ - .word solaris_getpeername /* getpeername dpp 243 */ - .word solaris_getsockname /* getsockname dpp 244 */ - .word solaris_getsockopt /* getsockopt dddpp 245 */ - .word solaris_setsockopt /* setsockopt dddpp 246 */ - .word solaris_unimplemented /* 247 */ - .word solaris_ntp_gettime /* ntp_gettime p 248 */ - .word solaris_ntp_adjtime /* ntp_adjtime p 249 */ - .word solaris_unimplemented /* 250 */ - .word solaris_unimplemented /* 251 */ - .word solaris_unimplemented /* 252 */ - .word solaris_unimplemented /* 253 */ - .word solaris_unimplemented /* 254 */ - .word solaris_unimplemented /* 255 */ diff --git a/arch/sparc64/solaris/timod.c b/arch/sparc64/solaris/timod.c deleted file mode 100644 index 15234fcd191a..000000000000 --- a/arch/sparc64/solaris/timod.c +++ /dev/null @@ -1,976 +0,0 @@ -/* $Id: timod.c,v 1.19 2002/02/08 03:57:14 davem Exp $ - * timod.c: timod emulation. - * - * Copyright (C) 1998 Patrik Rak (prak3264@ss1000.ms.mff.cuni.cz) - * - * Streams & timod emulation based on code - * Copyright (C) 1995, 1996 Mike Jagdis (jaggy@purplet.demon.co.uk) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include -#include - -#include "conv.h" -#include "socksys.h" - -asmlinkage int solaris_ioctl(unsigned int fd, unsigned int cmd, u32 arg); - -static DEFINE_SPINLOCK(timod_pagelock); -static char * page = NULL ; - -#ifndef DEBUG_SOLARIS_KMALLOC - -#define mykmalloc kmalloc -#define mykfree kfree - -#else - -void * mykmalloc(size_t s, gfp_t gfp) -{ - static char * page; - static size_t free; - void * r; - s = ((s + 63) & ~63); - if( s > PAGE_SIZE ) { - SOLD("too big size, calling real kmalloc"); - return kmalloc(s, gfp); - } - if( s > free ) { - /* we are wasting memory, but we don't care */ - page = (char *)__get_free_page(gfp); - free = PAGE_SIZE; - } - r = page; - page += s; - free -= s; - return r; -} - -void mykfree(void *p) -{ -} - -#endif - -#ifndef DEBUG_SOLARIS - -#define BUF_SIZE PAGE_SIZE -#define PUT_MAGIC(a,m) -#define SCHECK_MAGIC(a,m) -#define BUF_OFFSET 0 -#define MKCTL_TRAILER 0 - -#else - -#define BUF_SIZE (PAGE_SIZE-2*sizeof(u64)) -#define BUFPAGE_MAGIC 0xBADC0DEDDEADBABEL -#define MKCTL_MAGIC 0xDEADBABEBADC0DEDL -#define PUT_MAGIC(a,m) do{(*(u64*)(a))=(m);}while(0) -#define SCHECK_MAGIC(a,m) do{if((*(u64*)(a))!=(m))printk("%s,%u,%s(): magic %08x at %p corrupted!\n",\ - __FILE__,__LINE__,__func__,(m),(a));}while(0) -#define BUF_OFFSET sizeof(u64) -#define MKCTL_TRAILER sizeof(u64) - -#endif - -static char *getpage( void ) -{ - char *r; - SOLD("getting page"); - spin_lock(&timod_pagelock); - if (page) { - r = page; - page = NULL; - spin_unlock(&timod_pagelock); - SOLD("got cached"); - return r + BUF_OFFSET; - } - spin_unlock(&timod_pagelock); - SOLD("getting new"); - r = (char *)__get_free_page(GFP_KERNEL); - PUT_MAGIC(r,BUFPAGE_MAGIC); - PUT_MAGIC(r+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC); - return r + BUF_OFFSET; -} - -static void putpage(char *p) -{ - SOLD("putting page"); - p = p - BUF_OFFSET; - SCHECK_MAGIC(p,BUFPAGE_MAGIC); - SCHECK_MAGIC(p+PAGE_SIZE-sizeof(u64),BUFPAGE_MAGIC); - spin_lock(&timod_pagelock); - if (page) { - spin_unlock(&timod_pagelock); - free_page((unsigned long)p); - SOLD("freed it"); - } else { - page = p; - spin_unlock(&timod_pagelock); - SOLD("cached it"); - } -} - -static struct T_primsg *timod_mkctl(int size) -{ - struct T_primsg *it; - - SOLD("creating primsg"); - it = (struct T_primsg *)mykmalloc(size+sizeof(*it)-sizeof(s32)+2*MKCTL_TRAILER, GFP_KERNEL); - if (it) { - SOLD("got it"); - it->pri = MSG_HIPRI; - it->length = size; - PUT_MAGIC((char*)((u64)(((char *)&it->type)+size+7)&~7),MKCTL_MAGIC); - } - return it; -} - -static void timod_wake_socket(unsigned int fd) -{ - struct socket *sock; - struct fdtable *fdt; - - SOLD("wakeing socket"); - fdt = files_fdtable(current->files); - sock = SOCKET_I(fdt->fd[fd]->f_path.dentry->d_inode); - wake_up_interruptible(&sock->wait); - read_lock(&sock->sk->sk_callback_lock); - if (sock->fasync_list && !test_bit(SOCK_ASYNC_WAITDATA, &sock->flags)) - __kill_fasync(sock->fasync_list, SIGIO, POLL_IN); - read_unlock(&sock->sk->sk_callback_lock); - SOLD("done"); -} - -static void timod_queue(unsigned int fd, struct T_primsg *it) -{ - struct sol_socket_struct *sock; - struct fdtable *fdt; - - SOLD("queuing primsg"); - fdt = files_fdtable(current->files); - sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data; - it->next = sock->pfirst; - sock->pfirst = it; - if (!sock->plast) - sock->plast = it; - timod_wake_socket(fd); - SOLD("done"); -} - -static void timod_queue_end(unsigned int fd, struct T_primsg *it) -{ - struct sol_socket_struct *sock; - struct fdtable *fdt; - - SOLD("queuing primsg at end"); - fdt = files_fdtable(current->files); - sock = (struct sol_socket_struct *)fdt->fd[fd]->private_data; - it->next = NULL; - if (sock->plast) - sock->plast->next = it; - else - sock->pfirst = it; - sock->plast = it; - SOLD("done"); -} - -static void timod_error(unsigned int fd, int prim, int terr, int uerr) -{ - struct T_primsg *it; - - SOLD("making error"); - it = timod_mkctl(sizeof(struct T_error_ack)); - if (it) { - struct T_error_ack *err = (struct T_error_ack *)&it->type; - - SOLD("got it"); - err->PRIM_type = T_ERROR_ACK; - err->ERROR_prim = prim; - err->TLI_error = terr; - err->UNIX_error = uerr; /* FIXME: convert this */ - timod_queue(fd, it); - } - SOLD("done"); -} - -static void timod_ok(unsigned int fd, int prim) -{ - struct T_primsg *it; - struct T_ok_ack *ok; - - SOLD("creating ok ack"); - it = timod_mkctl(sizeof(*ok)); - if (it) { - SOLD("got it"); - ok = (struct T_ok_ack *)&it->type; - ok->PRIM_type = T_OK_ACK; - ok->CORRECT_prim = prim; - timod_queue(fd, it); - } - SOLD("done"); -} - -static int timod_optmgmt(unsigned int fd, int flag, char __user *opt_buf, int opt_len, int do_ret) -{ - int error, failed; - int ret_space, ret_len; - long args[5]; - char *ret_pos,*ret_buf; - int (*sys_socketcall)(int, unsigned long *) = - (int (*)(int, unsigned long *))SYS(socketcall); - mm_segment_t old_fs = get_fs(); - - SOLD("entry"); - SOLDD(("fd %u flg %u buf %p len %u doret %u",fd,flag,opt_buf,opt_len,do_ret)); - if (!do_ret && (!opt_buf || opt_len <= 0)) - return 0; - SOLD("getting page"); - ret_pos = ret_buf = getpage(); - ret_space = BUF_SIZE; - ret_len = 0; - - error = failed = 0; - SOLD("looping"); - while(opt_len >= sizeof(struct opthdr)) { - struct opthdr *opt; - int orig_opt_len; - SOLD("loop start"); - opt = (struct opthdr *)ret_pos; - if (ret_space < sizeof(struct opthdr)) { - failed = TSYSERR; - break; - } - SOLD("getting opthdr"); - if (copy_from_user(opt, opt_buf, sizeof(struct opthdr)) || - opt->len > opt_len) { - failed = TBADOPT; - break; - } - SOLD("got opthdr"); - if (flag == T_NEGOTIATE) { - char *buf; - - SOLD("handling T_NEGOTIATE"); - buf = ret_pos + sizeof(struct opthdr); - if (ret_space < opt->len + sizeof(struct opthdr) || - copy_from_user(buf, opt_buf+sizeof(struct opthdr), opt->len)) { - failed = TSYSERR; - break; - } - SOLD("got optdata"); - args[0] = fd; - args[1] = opt->level; - args[2] = opt->name; - args[3] = (long)buf; - args[4] = opt->len; - SOLD("calling SETSOCKOPT"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_SETSOCKOPT, args); - set_fs(old_fs); - if (error) { - failed = TBADOPT; - break; - } - SOLD("SETSOCKOPT ok"); - } - orig_opt_len = opt->len; - opt->len = ret_space - sizeof(struct opthdr); - if (opt->len < 0) { - failed = TSYSERR; - break; - } - args[0] = fd; - args[1] = opt->level; - args[2] = opt->name; - args[3] = (long)(ret_pos+sizeof(struct opthdr)); - args[4] = (long)&opt->len; - SOLD("calling GETSOCKOPT"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_GETSOCKOPT, args); - set_fs(old_fs); - if (error) { - failed = TBADOPT; - break; - } - SOLD("GETSOCKOPT ok"); - ret_space -= sizeof(struct opthdr) + opt->len; - ret_len += sizeof(struct opthdr) + opt->len; - ret_pos += sizeof(struct opthdr) + opt->len; - opt_len -= sizeof(struct opthdr) + orig_opt_len; - opt_buf += sizeof(struct opthdr) + orig_opt_len; - SOLD("loop end"); - } - SOLD("loop done"); - if (do_ret) { - SOLD("generating ret msg"); - if (failed) - timod_error(fd, T_OPTMGMT_REQ, failed, -error); - else { - struct T_primsg *it; - it = timod_mkctl(sizeof(struct T_optmgmt_ack) + ret_len); - if (it) { - struct T_optmgmt_ack *ack = - (struct T_optmgmt_ack *)&it->type; - SOLD("got primsg"); - ack->PRIM_type = T_OPTMGMT_ACK; - ack->OPT_length = ret_len; - ack->OPT_offset = sizeof(struct T_optmgmt_ack); - ack->MGMT_flags = (failed ? T_FAILURE : flag); - memcpy(((char*)ack)+sizeof(struct T_optmgmt_ack), - ret_buf, ret_len); - timod_queue(fd, it); - } - } - } - SOLDD(("put_page %p\n", ret_buf)); - putpage(ret_buf); - SOLD("done"); - return 0; -} - -int timod_putmsg(unsigned int fd, char __user *ctl_buf, int ctl_len, - char __user *data_buf, int data_len, int flags) -{ - int ret, error, terror; - char *buf; - struct file *filp; - struct inode *ino; - struct fdtable *fdt; - struct sol_socket_struct *sock; - mm_segment_t old_fs = get_fs(); - long args[6]; - int (*sys_socketcall)(int, unsigned long __user *) = - (int (*)(int, unsigned long __user *))SYS(socketcall); - int (*sys_sendto)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int) = - (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int))SYS(sendto); - - fdt = files_fdtable(current->files); - filp = fdt->fd[fd]; - ino = filp->f_path.dentry->d_inode; - sock = (struct sol_socket_struct *)filp->private_data; - SOLD("entry"); - if (get_user(ret, (int __user *)A(ctl_buf))) - return -EFAULT; - switch (ret) { - case T_BIND_REQ: - { - struct T_bind_req req; - - SOLDD(("bind %016lx(%016lx)\n", sock, filp)); - SOLD("T_BIND_REQ"); - if (sock->state != TS_UNBND) { - timod_error(fd, T_BIND_REQ, TOUTSTATE, 0); - return 0; - } - SOLD("state ok"); - if (copy_from_user(&req, ctl_buf, sizeof(req))) { - timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("got ctl req"); - if (req.ADDR_offset && req.ADDR_length) { - if (req.ADDR_length > BUF_SIZE) { - timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("req size ok"); - buf = getpage(); - if (copy_from_user(buf, ctl_buf + req.ADDR_offset, req.ADDR_length)) { - timod_error(fd, T_BIND_REQ, TSYSERR, EFAULT); - putpage(buf); - return 0; - } - SOLD("got ctl data"); - args[0] = fd; - args[1] = (long)buf; - args[2] = req.ADDR_length; - SOLD("calling BIND"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_BIND, args); - set_fs(old_fs); - putpage(buf); - SOLD("BIND returned"); - } else - error = 0; - if (!error) { - struct T_primsg *it; - if (req.CONIND_number) { - args[0] = fd; - args[1] = req.CONIND_number; - SOLD("calling LISTEN"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_LISTEN, args); - set_fs(old_fs); - SOLD("LISTEN done"); - } - it = timod_mkctl(sizeof(struct T_bind_ack)+sizeof(struct sockaddr)); - if (it) { - struct T_bind_ack *ack; - - ack = (struct T_bind_ack *)&it->type; - ack->PRIM_type = T_BIND_ACK; - ack->ADDR_offset = sizeof(*ack); - ack->ADDR_length = sizeof(struct sockaddr); - ack->CONIND_number = req.CONIND_number; - args[0] = fd; - args[1] = (long)(ack+sizeof(*ack)); - args[2] = (long)&ack->ADDR_length; - set_fs(KERNEL_DS); - sys_socketcall(SYS_GETSOCKNAME,args); - set_fs(old_fs); - sock->state = TS_IDLE; - timod_ok(fd, T_BIND_REQ); - timod_queue_end(fd, it); - SOLD("BIND done"); - return 0; - } - } - SOLD("some error"); - switch (error) { - case -EINVAL: - terror = TOUTSTATE; - error = 0; - break; - case -EACCES: - terror = TACCES; - error = 0; - break; - case -EADDRNOTAVAIL: - case -EADDRINUSE: - terror = TNOADDR; - error = 0; - break; - default: - terror = TSYSERR; - break; - } - timod_error(fd, T_BIND_REQ, terror, -error); - SOLD("BIND done"); - return 0; - } - case T_CONN_REQ: - { - struct T_conn_req req; - unsigned short oldflags; - struct T_primsg *it; - SOLD("T_CONN_REQ"); - if (sock->state != TS_UNBND && sock->state != TS_IDLE) { - timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); - return 0; - } - SOLD("state ok"); - if (copy_from_user(&req, ctl_buf, sizeof(req))) { - timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("got ctl req"); - if (ctl_len > BUF_SIZE) { - timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("req size ok"); - buf = getpage(); - if (copy_from_user(buf, ctl_buf, ctl_len)) { - timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); - putpage(buf); - return 0; - } -#ifdef DEBUG_SOLARIS - { - char * ptr = buf; - int len = ctl_len; - printk("returned data (%d bytes): ",len); - while( len-- ) { - if (!(len & 7)) - printk(" "); - printk("%02x",(unsigned char)*ptr++); - } - printk("\n"); - } -#endif - SOLD("got ctl data"); - args[0] = fd; - args[1] = (long)buf+req.DEST_offset; - args[2] = req.DEST_length; - oldflags = filp->f_flags; - filp->f_flags &= ~O_NONBLOCK; - SOLD("calling CONNECT"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_CONNECT, args); - set_fs(old_fs); - filp->f_flags = oldflags; - SOLD("CONNECT done"); - if (!error) { - struct T_conn_con *con; - SOLD("no error"); - it = timod_mkctl(ctl_len); - if (!it) { - putpage(buf); - return -ENOMEM; - } - con = (struct T_conn_con *)&it->type; -#ifdef DEBUG_SOLARIS - { - char * ptr = buf; - int len = ctl_len; - printk("returned data (%d bytes): ",len); - while( len-- ) { - if (!(len & 7)) - printk(" "); - printk("%02x",(unsigned char)*ptr++); - } - printk("\n"); - } -#endif - memcpy(con, buf, ctl_len); - SOLD("copied ctl_buf"); - con->PRIM_type = T_CONN_CON; - sock->state = TS_DATA_XFER; - } else { - struct T_discon_ind *dis; - SOLD("some error"); - it = timod_mkctl(sizeof(*dis)); - if (!it) { - putpage(buf); - return -ENOMEM; - } - SOLD("got primsg"); - dis = (struct T_discon_ind *)&it->type; - dis->PRIM_type = T_DISCON_IND; - dis->DISCON_reason = -error; /* FIXME: convert this as in iABI_errors() */ - dis->SEQ_number = 0; - } - putpage(buf); - timod_ok(fd, T_CONN_REQ); - it->pri = 0; - timod_queue_end(fd, it); - SOLD("CONNECT done"); - return 0; - } - case T_OPTMGMT_REQ: - { - struct T_optmgmt_req req; - SOLD("OPTMGMT_REQ"); - if (copy_from_user(&req, ctl_buf, sizeof(req))) - return -EFAULT; - SOLD("got req"); - return timod_optmgmt(fd, req.MGMT_flags, - req.OPT_offset > 0 ? ctl_buf + req.OPT_offset : NULL, - req.OPT_length, 1); - } - case T_UNITDATA_REQ: - { - struct T_unitdata_req req; - - int err; - SOLD("T_UNITDATA_REQ"); - if (sock->state != TS_IDLE && sock->state != TS_DATA_XFER) { - timod_error(fd, T_CONN_REQ, TOUTSTATE, 0); - return 0; - } - SOLD("state ok"); - if (copy_from_user(&req, ctl_buf, sizeof(req))) { - timod_error(fd, T_CONN_REQ, TSYSERR, EFAULT); - return 0; - } - SOLD("got ctl req"); -#ifdef DEBUG_SOLARIS - { - char * ptr = ctl_buf+req.DEST_offset; - int len = req.DEST_length; - printk("socket address (%d bytes): ",len); - while( len-- ) { - char c; - if (get_user(c,ptr)) - printk("??"); - else - printk("%02x",(unsigned char)c); - ptr++; - } - printk("\n"); - } -#endif - err = sys_sendto(fd, data_buf, data_len, 0, req.DEST_length > 0 ? (struct sockaddr __user *)(ctl_buf+req.DEST_offset) : NULL, req.DEST_length); - if (err == data_len) - return 0; - if(err >= 0) { - printk("timod: sendto failed to send all the data\n"); - return 0; - } - timod_error(fd, T_CONN_REQ, TSYSERR, -err); - return 0; - } - default: - printk(KERN_INFO "timod_putmsg: unsupported command %u.\n", ret); - break; - } - return -EINVAL; -} - -int timod_getmsg(unsigned int fd, char __user *ctl_buf, int ctl_maxlen, s32 __user *ctl_len, - char __user *data_buf, int data_maxlen, s32 __user *data_len, int *flags_p) -{ - int error; - int oldflags; - struct file *filp; - struct inode *ino; - struct fdtable *fdt; - struct sol_socket_struct *sock; - struct T_unitdata_ind udi; - mm_segment_t old_fs = get_fs(); - long args[6]; - char __user *tmpbuf; - int tmplen; - int (*sys_socketcall)(int, unsigned long __user *) = - (int (*)(int, unsigned long __user *))SYS(socketcall); - int (*sys_recvfrom)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *); - - SOLD("entry"); - SOLDD(("%u %p %d %p %p %d %p %d\n", fd, ctl_buf, ctl_maxlen, ctl_len, data_buf, data_maxlen, data_len, *flags_p)); - fdt = files_fdtable(current->files); - filp = fdt->fd[fd]; - ino = filp->f_path.dentry->d_inode; - sock = (struct sol_socket_struct *)filp->private_data; - SOLDD(("%p %p\n", sock->pfirst, sock->pfirst ? sock->pfirst->next : NULL)); - if ( ctl_maxlen > 0 && !sock->pfirst && SOCKET_I(ino)->type == SOCK_STREAM - && sock->state == TS_IDLE) { - SOLD("calling LISTEN"); - args[0] = fd; - args[1] = -1; - set_fs(KERNEL_DS); - sys_socketcall(SYS_LISTEN, args); - set_fs(old_fs); - SOLD("LISTEN done"); - } - if (!(filp->f_flags & O_NONBLOCK)) { - struct poll_wqueues wait_table; - poll_table *wait; - - poll_initwait(&wait_table); - wait = &wait_table.pt; - for(;;) { - SOLD("loop"); - set_current_state(TASK_INTERRUPTIBLE); - /* ! ( l<0 || ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ - /* ( ! l<0 && ! ( l>=0 && ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ - /* ( l>=0 && ( ! l>=0 || ! ( ! pfirst || (flags == HIPRI && pri != HIPRI) ) ) ) */ - /* ( l>=0 && ( l<0 || ( pfirst && ! (flags == HIPRI && pri != HIPRI) ) ) ) */ - /* ( l>=0 && ( l<0 || ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) ) */ - /* ( l>=0 && ( pfirst && (flags != HIPRI || pri == HIPRI) ) ) */ - if (ctl_maxlen >= 0 && sock->pfirst && (*flags_p != MSG_HIPRI || sock->pfirst->pri == MSG_HIPRI)) - break; - SOLD("cond 1 passed"); - if ( - #if 1 - *flags_p != MSG_HIPRI && - #endif - ((filp->f_op->poll(filp, wait) & POLLIN) || - (filp->f_op->poll(filp, NULL) & POLLIN) || - signal_pending(current)) - ) { - break; - } - if( *flags_p == MSG_HIPRI ) { - SOLD("avoiding lockup"); - break ; - } - if(wait_table.error) { - SOLD("wait-table error"); - poll_freewait(&wait_table); - return wait_table.error; - } - SOLD("scheduling"); - schedule(); - } - SOLD("loop done"); - current->state = TASK_RUNNING; - poll_freewait(&wait_table); - if (signal_pending(current)) { - SOLD("signal pending"); - return -EINTR; - } - } - if (ctl_maxlen >= 0 && sock->pfirst) { - struct T_primsg *it = sock->pfirst; - int l = min_t(int, ctl_maxlen, it->length); - SCHECK_MAGIC((char*)((u64)(((char *)&it->type)+sock->offset+it->length+7)&~7),MKCTL_MAGIC); - SOLD("purting ctl data"); - if(copy_to_user(ctl_buf, - (char*)&it->type + sock->offset, l)) - return -EFAULT; - SOLD("pur it"); - if(put_user(l, ctl_len)) - return -EFAULT; - SOLD("set ctl_len"); - *flags_p = it->pri; - it->length -= l; - if (it->length) { - SOLD("more ctl"); - sock->offset += l; - return MORECTL; - } else { - SOLD("removing message"); - sock->pfirst = it->next; - if (!sock->pfirst) - sock->plast = NULL; - SOLDD(("getmsg kfree %016lx->%016lx\n", it, sock->pfirst)); - mykfree(it); - sock->offset = 0; - SOLD("ctl done"); - return 0; - } - } - *flags_p = 0; - if (ctl_maxlen >= 0) { - SOLD("ACCEPT perhaps?"); - if (SOCKET_I(ino)->type == SOCK_STREAM && sock->state == TS_IDLE) { - struct T_conn_ind ind; - char *buf = getpage(); - int len = BUF_SIZE; - - SOLD("trying ACCEPT"); - if (put_user(ctl_maxlen - sizeof(ind), ctl_len)) - return -EFAULT; - args[0] = fd; - args[1] = (long)buf; - args[2] = (long)&len; - oldflags = filp->f_flags; - filp->f_flags |= O_NONBLOCK; - SOLD("calling ACCEPT"); - set_fs(KERNEL_DS); - error = sys_socketcall(SYS_ACCEPT, args); - set_fs(old_fs); - filp->f_flags = oldflags; - if (error < 0) { - SOLD("some error"); - putpage(buf); - return error; - } - if (error) { - SOLD("connect"); - putpage(buf); - if (sizeof(ind) > ctl_maxlen) { - SOLD("generating CONN_IND"); - ind.PRIM_type = T_CONN_IND; - ind.SRC_length = len; - ind.SRC_offset = sizeof(ind); - ind.OPT_length = ind.OPT_offset = 0; - ind.SEQ_number = error; - if(copy_to_user(ctl_buf, &ind, sizeof(ind))|| - put_user(sizeof(ind)+ind.SRC_length,ctl_len)) - return -EFAULT; - SOLD("CONN_IND created"); - } - if (data_maxlen >= 0) - put_user(0, data_len); - SOLD("CONN_IND done"); - return 0; - } - if (len>ctl_maxlen) { - SOLD("data don't fit"); - putpage(buf); - return -EFAULT; /* XXX - is this ok ? */ - } - if(copy_to_user(ctl_buf,buf,len) || put_user(len,ctl_len)){ - SOLD("can't copy data"); - putpage(buf); - return -EFAULT; - } - SOLD("ACCEPT done"); - putpage(buf); - } - } - SOLD("checking data req"); - if (data_maxlen <= 0) { - if (data_maxlen == 0) - put_user(0, data_len); - if (ctl_maxlen >= 0) - put_user(0, ctl_len); - return -EAGAIN; - } - SOLD("wants data"); - if (ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) { - SOLD("udi fits"); - tmpbuf = ctl_buf + sizeof(udi); - tmplen = ctl_maxlen - sizeof(udi); - } else { - SOLD("udi does not fit"); - tmpbuf = NULL; - tmplen = 0; - } - if (put_user(tmplen, ctl_len)) - return -EFAULT; - SOLD("set ctl_len"); - oldflags = filp->f_flags; - filp->f_flags |= O_NONBLOCK; - SOLD("calling recvfrom"); - sys_recvfrom = (int (*)(int, void __user *, size_t, unsigned, struct sockaddr __user *, int __user *))SYS(recvfrom); - error = sys_recvfrom(fd, data_buf, data_maxlen, 0, (struct sockaddr __user *)tmpbuf, ctl_len); - filp->f_flags = oldflags; - if (error < 0) - return error; - SOLD("error >= 0" ) ; - if (error && ctl_maxlen > sizeof(udi) && sock->state == TS_IDLE) { - SOLD("generating udi"); - udi.PRIM_type = T_UNITDATA_IND; - if (get_user(udi.SRC_length, ctl_len)) - return -EFAULT; - udi.SRC_offset = sizeof(udi); - udi.OPT_length = udi.OPT_offset = 0; - if (copy_to_user(ctl_buf, &udi, sizeof(udi)) || - put_user(sizeof(udi)+udi.SRC_length, ctl_len)) - return -EFAULT; - SOLD("udi done"); - } else { - if (put_user(0, ctl_len)) - return -EFAULT; - } - put_user(error, data_len); - SOLD("done"); - return 0; -} - -asmlinkage int solaris_getmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) -{ - struct file *filp; - struct inode *ino; - struct strbuf __user *ctlptr; - struct strbuf __user *datptr; - struct strbuf ctl, dat; - int __user *flgptr; - int flags; - int error = -EBADF; - struct fdtable *fdt; - - SOLD("entry"); - lock_kernel(); - if (fd >= sysctl_nr_open) - goto out; - - fdt = files_fdtable(current->files); - filp = fdt->fd[fd]; - if(!filp) goto out; - - ino = filp->f_path.dentry->d_inode; - if (!ino || !S_ISSOCK(ino->i_mode)) - goto out; - - ctlptr = (struct strbuf __user *)A(arg1); - datptr = (struct strbuf __user *)A(arg2); - flgptr = (int __user *)A(arg3); - - error = -EFAULT; - - if (ctlptr) { - if (copy_from_user(&ctl,ctlptr,sizeof(struct strbuf)) || - put_user(-1,&ctlptr->len)) - goto out; - } else - ctl.maxlen = -1; - - if (datptr) { - if (copy_from_user(&dat,datptr,sizeof(struct strbuf)) || - put_user(-1,&datptr->len)) - goto out; - } else - dat.maxlen = -1; - - if (get_user(flags,flgptr)) - goto out; - - switch (flags) { - case 0: - case MSG_HIPRI: - case MSG_ANY: - case MSG_BAND: - break; - default: - error = -EINVAL; - goto out; - } - - error = timod_getmsg(fd,A(ctl.buf),ctl.maxlen,&ctlptr->len, - A(dat.buf),dat.maxlen,&datptr->len,&flags); - - if (!error && put_user(flags,flgptr)) - error = -EFAULT; -out: - unlock_kernel(); - SOLD("done"); - return error; -} - -asmlinkage int solaris_putmsg(unsigned int fd, u32 arg1, u32 arg2, u32 arg3) -{ - struct file *filp; - struct inode *ino; - struct strbuf __user *ctlptr; - struct strbuf __user *datptr; - struct strbuf ctl, dat; - int flags = (int) arg3; - int error = -EBADF; - struct fdtable *fdt; - - SOLD("entry"); - lock_kernel(); - if (fd >= sysctl_nr_open) - goto out; - - fdt = files_fdtable(current->files); - filp = fdt->fd[fd]; - if(!filp) goto out; - - ino = filp->f_path.dentry->d_inode; - if (!ino) goto out; - - if (!S_ISSOCK(ino->i_mode) && - (imajor(ino) != 30 || iminor(ino) != 1)) - goto out; - - ctlptr = A(arg1); - datptr = A(arg2); - - error = -EFAULT; - - if (ctlptr) { - if (copy_from_user(&ctl,ctlptr,sizeof(ctl))) - goto out; - if (ctl.len < 0 && flags) { - error = -EINVAL; - goto out; - } - } else { - ctl.len = 0; - ctl.buf = 0; - } - - if (datptr) { - if (copy_from_user(&dat,datptr,sizeof(dat))) - goto out; - } else { - dat.len = 0; - dat.buf = 0; - } - - error = timod_putmsg(fd,A(ctl.buf),ctl.len, - A(dat.buf),dat.len,flags); -out: - unlock_kernel(); - SOLD("done"); - return error; -} diff --git a/fs/Kconfig.binfmt b/fs/Kconfig.binfmt index b5c3b6114add..853845abcca6 100644 --- a/fs/Kconfig.binfmt +++ b/fs/Kconfig.binfmt @@ -62,7 +62,7 @@ config BINFMT_SHARED_FLAT config BINFMT_AOUT tristate "Kernel support for a.out and ECOFF binaries" depends on ARCH_SUPPORTS_AOUT && \ - (X86_32 || ALPHA || ARM || M68K || SPARC32) + (X86_32 || ALPHA || ARM || M68K) ---help--- A.out (Assembler.OUTput) is a set of formats for libraries and executables used in the earliest versions of UNIX. Linux used diff --git a/include/asm-sparc/Kbuild b/include/asm-sparc/Kbuild index c6a55cf0d337..671223718f0a 100644 --- a/include/asm-sparc/Kbuild +++ b/include/asm-sparc/Kbuild @@ -5,7 +5,6 @@ header-y += asi.h header-y += bpp.h header-y += jsflash.h header-y += openpromio.h -header-y += pconf.h header-y += reg.h header-y += traps.h header-y += vfc_ioctls.h diff --git a/include/asm-sparc/a.out-core.h b/include/asm-sparc/a.out-core.h deleted file mode 100644 index e8fd338ed0b2..000000000000 --- a/include/asm-sparc/a.out-core.h +++ /dev/null @@ -1,52 +0,0 @@ -/* a.out coredump register dumper - * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ - -#ifndef _ASM_A_OUT_CORE_H -#define _ASM_A_OUT_CORE_H - -#ifdef __KERNEL__ - -#include - -/* - * fill in the user structure for an a.out core dump - */ -static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) -{ - unsigned long first_stack_page; - - dump->magic = SUNOS_CORE_MAGIC; - dump->len = sizeof(struct user); - dump->regs.psr = regs->psr; - dump->regs.pc = regs->pc; - dump->regs.npc = regs->npc; - dump->regs.y = regs->y; - /* fuck me plenty */ - memcpy(&dump->regs.regs[0], ®s->u_regs[1], (sizeof(unsigned long) * 15)); - dump->uexec = current->thread.core_exec; - dump->u_tsize = (((unsigned long) current->mm->end_code) - - ((unsigned long) current->mm->start_code)) & ~(PAGE_SIZE - 1); - dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))); - dump->u_dsize -= dump->u_tsize; - dump->u_dsize &= ~(PAGE_SIZE - 1); - first_stack_page = (regs->u_regs[UREG_FP] & ~(PAGE_SIZE - 1)); - dump->u_ssize = (TASK_SIZE - first_stack_page) & ~(PAGE_SIZE - 1); - memcpy(&dump->fpu.fpstatus.fregs.regs[0], ¤t->thread.float_regs[0], (sizeof(unsigned long) * 32)); - dump->fpu.fpstatus.fsr = current->thread.fsr; - dump->fpu.fpstatus.flags = dump->fpu.fpstatus.extra = 0; - dump->fpu.fpstatus.fpq_count = current->thread.fpqdepth; - memcpy(&dump->fpu.fpstatus.fpq[0], ¤t->thread.fpqueue[0], - ((sizeof(unsigned long) * 2) * 16)); - dump->sigcode = 0; -} - -#endif /* __KERNEL__ */ -#endif /* _ASM_A_OUT_CORE_H */ diff --git a/include/asm-sparc/a.out.h b/include/asm-sparc/a.out.h deleted file mode 100644 index 2f1c3748a068..000000000000 --- a/include/asm-sparc/a.out.h +++ /dev/null @@ -1,97 +0,0 @@ -#ifndef __SPARC_A_OUT_H__ -#define __SPARC_A_OUT_H__ - -#define SPARC_PGSIZE 0x2000 /* Thanks to the sun4 architecture... */ -#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */ - -#ifndef __ASSEMBLY__ - -struct exec { - unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */ - unsigned char a_toolversion:7; - unsigned char a_machtype; - unsigned short a_info; - unsigned int a_text; /* length of text, in bytes */ - unsigned int a_data; /* length of data, in bytes */ - unsigned int a_bss; /* length of bss, in bytes */ - unsigned int a_syms; /* length of symbol table, in bytes */ - unsigned int a_entry; /* where program begins */ - unsigned int a_trsize; - unsigned int a_drsize; -}; - -#endif /* !__ASSEMBLY__ */ - -/* Where in the file does the text information begin? */ -#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec)) - -/* Where do the Symbols start? */ -#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \ - (x).a_data + (x).a_trsize + \ - (x).a_drsize) - -/* Where does text segment go in memory after being loaded? */ -#define N_TXTADDR(x) (unsigned long)(((N_MAGIC(x) == ZMAGIC) && \ - ((x).a_entry < SPARC_PGSIZE)) ? \ - 0 : SPARC_PGSIZE) - -/* And same for the data segment.. */ -#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \ - (N_TXTADDR(x) + (x).a_text) \ - : (unsigned long) (_N_SEGMENT_ROUND (_N_TXTENDADDR(x)))) - -#define N_TRSIZE(a) ((a).a_trsize) -#define N_DRSIZE(a) ((a).a_drsize) -#define N_SYMSIZE(a) ((a).a_syms) - -#ifndef __ASSEMBLY__ - -/* - * Sparc relocation types - */ -enum reloc_type -{ - RELOC_8, - RELOC_16, - RELOC_32, /* simplest relocs */ - RELOC_DISP8, - RELOC_DISP16, - RELOC_DISP32, /* Disp's (pc-rel) */ - RELOC_WDISP30, - RELOC_WDISP22, /* SR word disp's */ - RELOC_HI22, - RELOC_22, /* SR 22-bit relocs */ - RELOC_13, - RELOC_LO10, /* SR 13&10-bit relocs */ - RELOC_SFA_BASE, - RELOC_SFA_OFF13, /* SR S.F.A. relocs */ - RELOC_BASE10, - RELOC_BASE13, - RELOC_BASE22, /* base_relative pic */ - RELOC_PC10, - RELOC_PC22, /* special pc-rel pic */ - RELOC_JMP_TBL, /* jmp_tbl_rel in pic */ - RELOC_SEGOFF16, /* ShLib offset-in-seg */ - RELOC_GLOB_DAT, - RELOC_JMP_SLOT, - RELOC_RELATIVE /* rtld relocs */ -}; - -/* - * Format of a relocation datum. - */ -struct relocation_info /* used when header.a_machtype == M_SPARC */ -{ - unsigned int r_address; /* relocation addr */ - unsigned int r_index:24; /* segment index or symbol index */ - unsigned int r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */ - unsigned int r_pad:2; /* */ - enum reloc_type r_type:5; /* type of relocation to perform */ - int r_addend; /* addend for relocation value */ -}; - -#define N_RELOCATION_INFO_DECLARED 1 - -#endif /* !(__ASSEMBLY__) */ - -#endif /* __SPARC_A_OUT_H__ */ diff --git a/include/asm-sparc/head.h b/include/asm-sparc/head.h index 1a03c28da92d..fcdba5116339 100644 --- a/include/asm-sparc/head.h +++ b/include/asm-sparc/head.h @@ -46,45 +46,12 @@ b linux_sparc_syscall; \ rd %psr, %l0; -/* Software trap for SunOS4.1.x system calls. */ -#define SUNOS_SYSCALL_TRAP \ - rd %psr, %l0; \ - sethi %hi(sunos_sys_table), %l7; \ - b linux_sparc_syscall; \ - or %l7, %lo(sunos_sys_table), %l7; - -#define SUNOS_NO_SYSCALL_TRAP \ - b sunos_syscall; \ - rd %psr, %l0; \ - nop; \ - nop; - -/* Software trap for Slowaris system calls. */ -#define SOLARIS_SYSCALL_TRAP \ - b solaris_syscall; \ - rd %psr, %l0; \ - nop; \ - nop; - -#define INDIRECT_SOLARIS_SYSCALL(x) \ - mov x, %g1; \ - b solaris_syscall; \ - rd %psr, %l0; \ - nop; - #define BREAKPOINT_TRAP \ b breakpoint_trap; \ rd %psr,%l0; \ nop; \ nop; -/* Software trap for Sparc-netbsd system calls. */ -#define NETBSD_SYSCALL_TRAP \ - sethi %hi(sys_call_table), %l7; \ - or %l7, %lo(sys_call_table), %l7; \ - b bsd_syscall; \ - rd %psr, %l0; - /* The Get Condition Codes software trap for userland. */ #define GETCC_TRAP \ b getcc_trap_handler; mov %psr, %l0; nop; nop; diff --git a/include/asm-sparc/ioctls.h b/include/asm-sparc/ioctls.h index 058c2064f706..3f4d0087b6a3 100644 --- a/include/asm-sparc/ioctls.h +++ b/include/asm-sparc/ioctls.h @@ -43,8 +43,6 @@ #define __TIOCSETX _IOW('t', 34, int) /* SunOS Specific */ #define __TIOCGETX _IOR('t', 35, int) /* SunOS Specific */ #define TIOCCONS _IO('t', 36) -#define __TIOCSSIZE _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */ -#define __TIOCGSIZE _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */ #define TIOCGSOFTCAR _IOR('t', 100, int) #define TIOCSSOFTCAR _IOW('t', 101, int) #define __TIOCUCNTL _IOW('t', 102, int) /* SunOS Specific */ diff --git a/include/asm-sparc/mman.h b/include/asm-sparc/mman.h index b7dc40bc68f4..e18be984c01d 100644 --- a/include/asm-sparc/mman.h +++ b/include/asm-sparc/mman.h @@ -22,19 +22,6 @@ #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ #define MAP_NONBLOCK 0x10000 /* do not block on IO */ -/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system - * XXX calls. - */ - -/* SunOS sys_mctl() stuff... */ -#define MC_SYNC 1 /* Sync pages in memory with storage (usu. a file) */ -#define MC_LOCK 2 /* Lock pages into core ram, do not allow swapping of them */ -#define MC_UNLOCK 3 /* Unlock pages locked via previous mctl() with MC_LOCK arg */ -#define MC_LOCKAS 5 /* Lock an entire address space of the calling process */ -#define MC_UNLOCKAS 6 /* Unlock entire address space of calling process */ - -#define MADV_FREE 0x5 /* (Solaris) contents can be freed */ - #ifdef __KERNEL__ #ifndef __ASSEMBLY__ #define arch_mmap_check sparc_mmap_check diff --git a/include/asm-sparc/namei.h b/include/asm-sparc/namei.h index f2461e8a11ac..618344d89cc4 100644 --- a/include/asm-sparc/namei.h +++ b/include/asm-sparc/namei.h @@ -8,19 +8,6 @@ #ifndef __SPARC_NAMEI_H #define __SPARC_NAMEI_H -#define SPARC_BSD_EMUL "/usr/gnemul/sunos/" -#define SPARC_SOL_EMUL "/usr/gnemul/solaris/" - -static inline char * __emul_prefix(void) -{ - switch (current->personality) { - case PER_SUNOS: - return SPARC_BSD_EMUL; - case PER_SVR4: - return SPARC_SOL_EMUL; - default: - return NULL; - } -} +#define __emul_prefix() NULL #endif /* __SPARC_NAMEI_H */ diff --git a/include/asm-sparc/pconf.h b/include/asm-sparc/pconf.h deleted file mode 100644 index d73c1f1c49dc..000000000000 --- a/include/asm-sparc/pconf.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $Id: pconf.h,v 1.3 1996/04/25 06:13:25 davem Exp $ - * pconf.h: pathconf() and fpathconf() defines for SunOS - * system call compatibility. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#ifndef _SPARC_PCONF_H -#define _SPARC_PCONF_H - -#include -#include - -#define _PCONF_LINK 1 /* Max number of links to an object */ -#define _PCONF_CANON 2 /* TTY input buffer line size */ -#define _PCONF_INPUT 3 /* Biggest packet a tty can imbibe at once */ -#define _PCONF_NAME 4 /* Filename length max */ -#define _PCONF_PATH 5 /* Max size of a pathname */ -#define _PCONF_PIPE 6 /* Buffer size for a pipe */ -#define _PCONF_CHRESTRICT 7 /* Can only root chown files? */ -#define _PCONF_NOTRUNC 8 /* Are pathnames truncated if too big? */ -#define _PCONF_VDISABLE 9 /* Magic char to disable special tty chars */ -#define _PCONF_MAXPCONF 9 - -#endif /* !(_SPARC_PCONF_H) */ diff --git a/include/asm-sparc/processor.h b/include/asm-sparc/processor.h index 40b1e41fdea7..e3006979709b 100644 --- a/include/asm-sparc/processor.h +++ b/include/asm-sparc/processor.h @@ -13,8 +13,6 @@ */ #define current_text_addr() ({ void *pc; __asm__("sethi %%hi(1f), %0; or %0, %%lo(1f), %0;\n1:" : "=r" (pc)); pc; }) -#include - #include #include #include @@ -67,7 +65,6 @@ struct thread_struct { struct fpq fpqueue[16]; unsigned long flags; mm_segment_t current_ds; - struct exec core_exec; /* just what it says. */ int new_signal; }; diff --git a/include/asm-sparc/socket.h b/include/asm-sparc/socket.h index 2e2bd0b7c8e3..a00e15df227c 100644 --- a/include/asm-sparc/socket.h +++ b/include/asm-sparc/socket.h @@ -24,9 +24,6 @@ #define SO_SNDTIMEO 0x4000 #define SO_ACCEPTCONN 0x8000 -/* wha!??? */ -#define SO_DONTLINGER (~SO_LINGER) /* Older SunOS compat. hack */ - #define SO_SNDBUF 0x1001 #define SO_RCVBUF 0x1002 #define SO_SNDBUFFORCE 0x100a diff --git a/include/asm-sparc/solerrno.h b/include/asm-sparc/solerrno.h deleted file mode 100644 index 8abce7e4639f..000000000000 --- a/include/asm-sparc/solerrno.h +++ /dev/null @@ -1,132 +0,0 @@ -/* $Id: solerrno.h,v 1.5 1996/04/25 06:13:32 davem Exp $ - * solerrno.h: Solaris error return codes for compatibility. - * - * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) - */ - -#ifndef _SPARC_SOLERRNO_H -#define _SPARC_SOLERRNO_H - -#define SOL_EPERM 1 /* Required superuser access perms */ -#define SOL_ENOENT 2 /* File or directory does not exist */ -#define SOL_ESRCH 3 /* Process did not exist */ -#define SOL_EINTR 4 /* System call was interrupted */ -#define SOL_EIO 5 /* An i/o error occurred */ -#define SOL_ENXIO 6 /* Device or Address does not exist */ -#define SOL_E2BIG 7 /* Too many arguments were given */ -#define SOL_ENOEXEC 8 /* Header of executable was munged */ -#define SOL_EBADF 9 /* Bogus file number */ -#define SOL_ECHILD 10 /* No children of process exist */ -#define SOL_EAGAIN 11 /* beep beep, "try again later" */ -#define SOL_ENOMEM 12 /* No memory available */ -#define SOL_EACCES 13 /* Access not allowed */ -#define SOL_EFAULT 14 /* Address passed was invalid */ -#define SOL_ENOTBLK 15 /* blkdev op on non-block device */ -#define SOL_EBUSY 16 /* Mounted device was busy */ -#define SOL_EEXIST 17 /* File specified already exists */ -#define SOL_EXDEV 18 /* Link request across diff devices */ -#define SOL_ENODEV 19 /* Device does not exist on system */ -#define SOL_ENOTDIR 20 /* Dir operation on non-directory */ -#define SOL_EISDIR 21 /* File was of directory type */ -#define SOL_EINVAL 22 /* Argument passed was invalid */ -#define SOL_ENFILE 23 /* No more room in file table */ -#define SOL_EMFILE 24 /* Proc has too many files open */ -#define SOL_ENOTTY 25 /* Ioctl was invalid for req device */ -#define SOL_ETXTBSY 26 /* Text file in busy state */ -#define SOL_EFBIG 27 /* Too big of a file for operation */ -#define SOL_ENOSPC 28 /* Disk is full */ -#define SOL_ESPIPE 29 /* Seek attempted on non-seeking dev*/ -#define SOL_EROFS 30 /* Write attempted on read-only fs */ -#define SOL_EMLINK 31 /* Too many links in file search */ -#define SOL_EPIPE 32 /* Call a plumber */ -#define SOL_EDOM 33 /* Argument was out of fct domain */ -#define SOL_ERANGE 34 /* Could not represent math result */ -#define SOL_ENOMSG 35 /* Message of req type doesn't exist */ -#define SOL_EIDRM 36 /* Identifier has been removed */ -#define SOL_ECHRNG 37 /* Req channel number out of range */ -#define SOL_EL2NSYNC 38 /* Could not sync at run level 2 */ -#define SOL_EL3HLT 39 /* Halted at run level 3 */ -#define SOL_EL3RST 40 /* Reset at run level 3 */ -#define SOL_ELNRNG 41 /* Out of range link number */ -#define SOL_EUNATCH 42 /* Driver for protocol not attached */ -#define SOL_ENOCSI 43 /* CSI structure not around */ -#define SOL_EL2HLT 44 /* Halted at run level 2 */ -#define SOL_EDEADLK 45 /* Deadlock condition detected */ -#define SOL_ENOLCK 46 /* Record locks unavailable */ -#define SOL_ECANCELED 47 /* Cancellation of oper. happened */ -#define SOL_ENOTSUP 48 /* Attempt of unsupported operation */ -#define SOL_EDQUOT 49 /* Users disk quota exceeded */ -#define SOL_EBADE 50 /* Invalid exchange */ -#define SOL_EBADR 51 /* Request descriptor was invalid */ -#define SOL_EXFULL 52 /* Full exchange */ -#define SOL_ENOANO 53 /* ano does not exist */ -#define SOL_EBADRQC 54 /* Req code was invalid */ -#define SOL_EBADSLT 55 /* Bad slot number */ -#define SOL_EDEADLOCK 56 /* Deadlock in fs error */ -#define SOL_EBFONT 57 /* Font file format invalid */ -/* YOW, I LOVE SYSV STREAMS!!!! */ -#define SOL_ENOSTR 60 /* Stream-op on non-stream dev */ -#define SOL_ENODATA 61 /* No data avail at this time */ -#define SOL_ETIME 62 /* Expiration of time occurred */ -#define SOL_ENOSR 63 /* Streams resources exhausted */ -#define SOL_ENONET 64 /* No network connected */ -#define SOL_ENOPKG 65 /* Non-installed package */ -#define SOL_EREMOTE 66 /* Object was on remote machine */ -#define SOL_ENOLINK 67 /* Cut link */ -#define SOL_EADV 68 /* Error in advertise */ -#define SOL_ESRMNT 69 /* Some magic srmount problem */ -#define SOL_ECOMM 70 /* During send, comm error occurred */ -#define SOL_EPROTO 71 /* Protocol botch */ -#define SOL_EMULTIHOP 74 /* Multihop attempted */ -#define SOL_EBADMSG 77 /* Message was unreadable */ -#define SOL_ENAMETOOLONG 78 /* Too long of a path name */ -#define SOL_EOVERFLOW 79 /* Data type too small for datum */ -#define SOL_ENOTUNIQ 80 /* Logical name was not unique */ -#define SOL_EBADFD 81 /* Op cannot be performed on fd */ -#define SOL_EREMCHG 82 /* Remote address is now different */ -#define SOL_ELIBACC 83 /* Shared lib could not be accessed */ -#define SOL_ELIBBAD 84 /* ShLib is corrupted in some way */ -#define SOL_ELIBSCN 85 /* A.out ShLib problems */ -#define SOL_ELIBMAX 86 /* Exceeded ShLib linkage limit */ -#define SOL_ELIBEXEC 87 /* Execution of ShLib attempted */ -#define SOL_EILSEQ 88 /* Bad byte sequence found */ -#define SOL_ENOSYS 89 /* Invalid filesystem operation */ -#define SOL_ELOOP 90 /* Detected loop in symbolic links */ -#define SOL_ERESTART 91 /* System call is restartable */ -#define SOL_ESTRPIPE 92 /* Do not sleep in head of stream */ -#define SOL_ENOTEMPTY 93 /* Rmdir of non-empty directory */ -#define SOL_EUSERS 94 /* Over abundance of users for ufs */ -#define SOL_ENOTSOCK 95 /* Sock-op on non-sock */ -#define SOL_EDESTADDRREQ 96 /* No dest addr given, but needed */ -#define SOL_EMSGSIZE 97 /* Msg too big */ -#define SOL_EPROTOTYPE 98 /* Bad socket protocol */ -#define SOL_ENOPROTOOPT 99 /* Unavailable protocol */ -#define SOL_EPROTONOSUPPORT 120 /* Unsupported protocol */ -#define SOL_ESOCKTNOSUPPORT 121 /* Unsupported socket type */ -#define SOL_EOPNOTSUPP 122 /* Unsupported sock-op */ -#define SOL_EPFNOSUPPORT 123 /* Unsupported protocol family */ -#define SOL_EAFNOSUPPORT 124 /* Unsup addr family for protocol */ -#define SOL_EADDRINUSE 125 /* Req addr is already in use */ -#define SOL_EADDRNOTAVAIL 126 /* Req addr not available right now */ -#define SOL_ENETDOWN 127 /* Your subnet is on fire */ -#define SOL_ENETUNREACH 128 /* Someone playing with gateway and */ - /* did not tell you he was going to */ -#define SOL_ENETRESET 129 /* Buy less-buggy ethernet cards */ -#define SOL_ECONNABORTED 130 /* Aborted connection due to sw */ -#define SOL_ECONNRESET 131 /* Your peers reset your connection */ -#define SOL_ENOBUFS 132 /* No buffer space available */ -#define SOL_EISCONN 133 /* Connect on already connected */ - /* socket attempted */ -#define SOL_ENOTCONN 134 /* Comm on non-connected socket */ -#define SOL_ESHUTDOWN 143 /* Op attempted after sock-shutdown */ -#define SOL_ETOOMANYREFS 144 /* Reference limit exceeded */ -#define SOL_ETIMEDOUT 145 /* Timed out connection */ -#define SOL_ECONNREFUSED 146 /* Connection refused by remote host*/ -#define SOL_EHOSTDOWN 147 /* Remote host is up in flames */ -#define SOL_EHOSTUNREACH 148 /* Make a left at Easton Ave..... */ -#define SOL_EWOULDBLOCK EAGAIN /* Just an alias */ -#define SOL_EALREADY 149 /* Operation is already occurring */ -#define SOL_EINPROGRESS 150 /* Operation is happening now */ -#define SOL_ESTALE 151 /* Fungus growth on NFS file handle */ - -#endif /* !(_SPARC_SOLERRNO_H) */ diff --git a/include/asm-sparc/svr4.h b/include/asm-sparc/svr4.h deleted file mode 100644 index da1f1c980e2d..000000000000 --- a/include/asm-sparc/svr4.h +++ /dev/null @@ -1,119 +0,0 @@ -/* Solaris/SPARC constants and definitions -- - * (C) 1996 Miguel de Icaza - * - * This file is not meant to be included by user level applications - * but the solaris syscall emulator - */ - -#ifndef _SPARC_SVR4_H -#define _SPARC_SVR4_H - -/* Signals as used by svr4 */ -typedef struct { /* signal set type */ - ulong sigbits[4]; -} svr4_sigset_t; - -/* Values for siginfo.code */ -#define SVR4_SINOINFO 32767 -/* Siginfo, sucker expects bunch of information on those parameters */ -typedef union { - char total_size [128]; - struct { - int signo; - int code; - int error; - union { - } data; - } siginfo; -} svr4_siginfo_t; - -/* Context definition */ - -/* Location of the user stored registers into a greg_t */ -enum { - SVR4_PSR, SVR4_PC, SVR4_NPC, SVR4_Y, - SVR4_G1, SVR4_G2, SVR4_G3, SVR4_G4, - SVR4_G5, SVR4_G6, SVR4_G7, SVR4_O0, - SVR4_O1, SVR4_O2, SVR4_O3, SVR4_O4, - SVR4_O5, SVR4_O6, SVR4_O7 -}; - -/* sizeof (regs) / sizeof (greg_t), defined in the ABI */ -#define SVR4_NREGS 19 -#define SVR4_MAXWIN 31 - -typedef struct { - uint rwin_lo[8]; - uint rwin_in[8]; -} svr4_rwindow_t; - -typedef struct { - int count; - int __user *winptr [SVR4_MAXWIN]; /* pointer to the windows */ - svr4_rwindow_t win[SVR4_MAXWIN]; /* the windows */ -} svr4_gwindows_t; - -typedef int svr4_gregset_t[SVR4_NREGS]; - -typedef struct { - double fpu_regs[32]; - void *fp_q; - unsigned fp_fsr; - u_char fp_nqel; - u_char fp_nqsize; - u_char inuse; /* if fpu is in use */ -} svr4_fregset_t; - -typedef struct { - uint id; /* if this holds "xrs" string => ptr is valid */ - caddr_t ptr; -} svr4_xrs_t; - -/* Machine dependent context */ -typedef struct { - svr4_gregset_t greg; /* registers 0..19 (see top) */ - svr4_gwindows_t __user *gwin; /* may point to register windows */ - svr4_fregset_t freg; /* floating point registers */ - svr4_xrs_t xrs; /* mhm? */ - long pad[19]; -} svr4_mcontext_t; - -/* flags for stack_t.flags */ -enum svr4_stack_flags { - SVR4_SS_ONSTACK, - SVR4_SS_DISABLE, -}; - -/* signal stack exection place, unsupported */ -typedef struct svr4_stack_t { - char __user *sp; - int size; - int flags; -} svr4_stack_t; - -/* Context used by getcontext and setcontext */ -typedef struct svr4_ucontext_t { - u_long flags; /* context flags, indicate what is loaded */ - struct svr4_ucontext *link; - svr4_sigset_t sigmask; - svr4_stack_t stack; - svr4_mcontext_t mcontext; - long pad[23]; -} svr4_ucontext_t; - -/* windows hold the windows as they were at signal time, - * ucontext->mcontext holds a pointer to them. - * addresses for uc and si are passed as parameters to svr4 signal - * handler - */ - -/* This is the signal frame that is passed to the signal handler */ -typedef struct { - svr4_gwindows_t gw; /* windows */ - svr4_ucontext_t uc; /* machine context */ - svr4_siginfo_t si; /* siginfo */ -} svr4_signal_frame_t; - -#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7))) - -#endif /* include control */ diff --git a/include/asm-sparc/termios.h b/include/asm-sparc/termios.h index 4333232abb9f..733d40504e1e 100644 --- a/include/asm-sparc/termios.h +++ b/include/asm-sparc/termios.h @@ -33,11 +33,6 @@ struct ltchars { }; #endif /* __KERNEL__ */ -struct sunos_ttysize { - int st_lines; /* Lines on the terminal */ - int st_columns; /* Columns on the terminal */ -}; - struct winsize { unsigned short ws_row; unsigned short ws_col; diff --git a/include/asm-sparc/user.h b/include/asm-sparc/user.h index b5f1abf733d5..3400ea87f148 100644 --- a/include/asm-sparc/user.h +++ b/include/asm-sparc/user.h @@ -1,60 +1,6 @@ -/* $Id: user.h,v 1.5 1998/02/23 01:49:22 rth Exp $ - * asm-sparc/user.h: Core file definitions for the Sparc. - * - * Keep in sync with reg.h. Actually, we could get rid of this - * one, since we won't a.out core dump that much anyways - miguel. - * Copyright (C) 1995 (davem@caip.rutgers.edu) - */ #ifndef _SPARC_USER_H #define _SPARC_USER_H -#include -struct sunos_regs { - unsigned long psr, pc, npc, y; - unsigned long regs[15]; -}; - -struct sunos_fpqueue { - unsigned long *addr; - unsigned long inst; -}; - -struct sunos_fp { - union { - unsigned long regs[32]; - double reg_dbls[16]; - } fregs; - unsigned long fsr; - unsigned long flags; - unsigned long extra; - unsigned long fpq_count; - struct sunos_fpqueue fpq[16]; -}; - -struct sunos_fpu { - struct sunos_fp fpstatus; -}; - -/* The SunOS core file header layout. */ -struct user { - unsigned long magic; - unsigned long len; - struct sunos_regs regs; - struct exec uexec; - int signal; - size_t u_tsize; /* all of these in bytes! */ - size_t u_dsize; - size_t u_ssize; - char u_comm[17]; - struct sunos_fpu fpu; - unsigned long sigcode; /* Special sigcontext subcode, if any */ -}; - -#define NBPG 0x2000 -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_DATA_START_ADDR (u.uexec.a_data) -#define HOST_STACK_END_ADDR (- u.u_ssize * NBPG) -#define SUNOS_CORE_MAGIC 0x080456 +/* Nothing to define. */ #endif /* !(_SPARC_USER_H) */ diff --git a/include/asm-sparc64/Kbuild b/include/asm-sparc64/Kbuild index a90dc82129d1..dce1cf9a9313 100644 --- a/include/asm-sparc64/Kbuild +++ b/include/asm-sparc64/Kbuild @@ -12,7 +12,6 @@ header-y += display7seg.h header-y += envctrl.h header-y += openprom.h header-y += openpromio.h -header-y += pconf.h header-y += psrcompat.h header-y += pstate.h header-y += reg.h diff --git a/include/asm-sparc64/a.out-core.h b/include/asm-sparc64/a.out-core.h deleted file mode 100644 index 3499b3c425ca..000000000000 --- a/include/asm-sparc64/a.out-core.h +++ /dev/null @@ -1,31 +0,0 @@ -/* a.out coredump register dumper - * - * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ - -#ifndef _ASM_A_OUT_CORE_H -#define _ASM_A_OUT_CORE_H - -#ifdef __KERNEL__ - -#include - -/* - * fill in the user structure for an a.out core dump - */ -static inline void aout_dump_thread(struct pt_regs *regs, struct user *dump) -{ - /* Only should be used for SunOS and ancient a.out - * SparcLinux binaries... Not worth implementing. - */ - memset(dump, 0, sizeof(struct user)); -} - -#endif /* __KERNEL__ */ -#endif /* _ASM_A_OUT_CORE_H */ diff --git a/include/asm-sparc64/a.out.h b/include/asm-sparc64/a.out.h deleted file mode 100644 index 44208c2a188e..000000000000 --- a/include/asm-sparc64/a.out.h +++ /dev/null @@ -1 +0,0 @@ -#include diff --git a/include/asm-sparc64/ioctls.h b/include/asm-sparc64/ioctls.h index 083c9a0f37de..c1be40647c99 100644 --- a/include/asm-sparc64/ioctls.h +++ b/include/asm-sparc64/ioctls.h @@ -44,8 +44,6 @@ #define __TIOCSETX _IOW('t', 34, int) /* SunOS Specific */ #define __TIOCGETX _IOR('t', 35, int) /* SunOS Specific */ #define TIOCCONS _IO('t', 36) -#define __TIOCSSIZE _IOW('t', 37, struct sunos_ttysize) /* SunOS Specific */ -#define __TIOCGSIZE _IOR('t', 38, struct sunos_ttysize) /* SunOS Specific */ #define TIOCGSOFTCAR _IOR('t', 100, int) #define TIOCSSOFTCAR _IOW('t', 101, int) #define __TIOCUCNTL _IOW('t', 102, int) /* SunOS Specific */ diff --git a/include/asm-sparc64/mman.h b/include/asm-sparc64/mman.h index 8cc1860be630..e584563b56eb 100644 --- a/include/asm-sparc64/mman.h +++ b/include/asm-sparc64/mman.h @@ -22,19 +22,6 @@ #define MAP_POPULATE 0x8000 /* populate (prefault) pagetables */ #define MAP_NONBLOCK 0x10000 /* do not block on IO */ -/* XXX Need to add flags to SunOS's mctl, mlockall, and madvise system - * XXX calls. - */ - -/* SunOS sys_mctl() stuff... */ -#define MC_SYNC 1 /* Sync pages in memory with storage (usu. a file) */ -#define MC_LOCK 2 /* Lock pages into core ram, do not allow swapping of them */ -#define MC_UNLOCK 3 /* Unlock pages locked via previous mctl() with MC_LOCK arg */ -#define MC_LOCKAS 5 /* Lock an entire address space of the calling process */ -#define MC_UNLOCKAS 6 /* Unlock entire address space of calling process */ - -#define MADV_FREE 0x5 /* (Solaris) contents can be freed */ - #ifdef __KERNEL__ #ifndef __ASSEMBLY__ #define arch_mmap_check sparc64_mmap_check diff --git a/include/asm-sparc64/namei.h b/include/asm-sparc64/namei.h index ccda19e28695..275161f21213 100644 --- a/include/asm-sparc64/namei.h +++ b/include/asm-sparc64/namei.h @@ -8,19 +8,6 @@ #ifndef __SPARC64_NAMEI_H #define __SPARC64_NAMEI_H -#define SPARC_BSD_EMUL "/usr/gnemul/sunos/" -#define SPARC_SOL_EMUL "/usr/gnemul/solaris/" - -static inline char * __emul_prefix(void) -{ - switch (current->personality) { - case PER_SUNOS: - return SPARC_BSD_EMUL; - case PER_SVR4: - return SPARC_SOL_EMUL; - default: - return NULL; - } -} +#define __emul_prefix() NULL #endif /* __SPARC64_NAMEI_H */ diff --git a/include/asm-sparc64/pconf.h b/include/asm-sparc64/pconf.h deleted file mode 100644 index aad106a70908..000000000000 --- a/include/asm-sparc64/pconf.h +++ /dev/null @@ -1,25 +0,0 @@ -/* $Id: pconf.h,v 1.1 1996/12/02 00:09:10 davem Exp $ - * pconf.h: pathconf() and fpathconf() defines for SunOS - * system call compatibility. - * - * Copyright (C) 1995, 1996 David S. Miller (davem@caip.rutgers.edu) - */ - -#ifndef _SPARC64_PCONF_H -#define _SPARC64_PCONF_H - -#include -#include - -#define _PCONF_LINK 1 /* Max number of links to an object */ -#define _PCONF_CANON 2 /* TTY input buffer line size */ -#define _PCONF_INPUT 3 /* Biggest packet a tty can imbibe at once */ -#define _PCONF_NAME 4 /* Filename length max */ -#define _PCONF_PATH 5 /* Max size of a pathname */ -#define _PCONF_PIPE 6 /* Buffer size for a pipe */ -#define _PCONF_CHRESTRICT 7 /* Can only root chown files? */ -#define _PCONF_NOTRUNC 8 /* Are pathnames truncated if too big? */ -#define _PCONF_VDISABLE 9 /* Magic char to disable special tty chars */ -#define _PCONF_MAXPCONF 9 - -#endif /* !(_SPARC64_PCONF_H) */ diff --git a/include/asm-sparc64/socket.h b/include/asm-sparc64/socket.h index 44a625af6e31..8cf071fae3eb 100644 --- a/include/asm-sparc64/socket.h +++ b/include/asm-sparc64/socket.h @@ -24,9 +24,6 @@ #define SO_SNDTIMEO 0x4000 #define SO_ACCEPTCONN 0x8000 -/* wha!??? */ -#define SO_DONTLINGER (~SO_LINGER) /* Older SunOS compat. hack */ - #define SO_SNDBUF 0x1001 #define SO_RCVBUF 0x1002 #define SO_SNDBUFFORCE 0x100a diff --git a/include/asm-sparc64/solerrno.h b/include/asm-sparc64/solerrno.h deleted file mode 100644 index a2ea6fcf3446..000000000000 --- a/include/asm-sparc64/solerrno.h +++ /dev/null @@ -1,132 +0,0 @@ -/* $Id: solerrno.h,v 1.1 1996/12/26 14:22:40 davem Exp $ - * solerrno.h: Solaris error return codes for compatibility. - * - * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu) - */ - -#ifndef _SPARC64_SOLERRNO_H -#define _SPARC64_SOLERRNO_H - -#define SOL_EPERM 1 /* Required superuser access perms */ -#define SOL_ENOENT 2 /* File or directory does not exist */ -#define SOL_ESRCH 3 /* Process did not exist */ -#define SOL_EINTR 4 /* System call was interrupted */ -#define SOL_EIO 5 /* An i/o error occurred */ -#define SOL_ENXIO 6 /* Device or Address does not exist */ -#define SOL_E2BIG 7 /* Too many arguments were given */ -#define SOL_ENOEXEC 8 /* Header of executable was munged */ -#define SOL_EBADF 9 /* Bogus file number */ -#define SOL_ECHILD 10 /* No children of process exist */ -#define SOL_EAGAIN 11 /* beep beep, "try again later" */ -#define SOL_ENOMEM 12 /* No memory available */ -#define SOL_EACCES 13 /* Access not allowed */ -#define SOL_EFAULT 14 /* Address passed was invalid */ -#define SOL_ENOTBLK 15 /* blkdev op on non-block device */ -#define SOL_EBUSY 16 /* Mounted device was busy */ -#define SOL_EEXIST 17 /* File specified already exists */ -#define SOL_EXDEV 18 /* Link request across diff devices */ -#define SOL_ENODEV 19 /* Device does not exist on system */ -#define SOL_ENOTDIR 20 /* Dir operation on non-directory */ -#define SOL_EISDIR 21 /* File was of directory type */ -#define SOL_EINVAL 22 /* Argument passed was invalid */ -#define SOL_ENFILE 23 /* No more room in file table */ -#define SOL_EMFILE 24 /* Proc has too many files open */ -#define SOL_ENOTTY 25 /* Ioctl was invalid for req device */ -#define SOL_ETXTBSY 26 /* Text file in busy state */ -#define SOL_EFBIG 27 /* Too big of a file for operation */ -#define SOL_ENOSPC 28 /* Disk is full */ -#define SOL_ESPIPE 29 /* Seek attempted on non-seeking dev*/ -#define SOL_EROFS 30 /* Write attempted on read-only fs */ -#define SOL_EMLINK 31 /* Too many links in file search */ -#define SOL_EPIPE 32 /* Call a plumber */ -#define SOL_EDOM 33 /* Argument was out of fct domain */ -#define SOL_ERANGE 34 /* Could not represent math result */ -#define SOL_ENOMSG 35 /* Message of req type doesn't exist */ -#define SOL_EIDRM 36 /* Identifier has been removed */ -#define SOL_ECHRNG 37 /* Req channel number out of range */ -#define SOL_EL2NSYNC 38 /* Could not sync at run level 2 */ -#define SOL_EL3HLT 39 /* Halted at run level 3 */ -#define SOL_EL3RST 40 /* Reset at run level 3 */ -#define SOL_ELNRNG 41 /* Out of range link number */ -#define SOL_EUNATCH 42 /* Driver for protocol not attached */ -#define SOL_ENOCSI 43 /* CSI structure not around */ -#define SOL_EL2HLT 44 /* Halted at run level 2 */ -#define SOL_EDEADLK 45 /* Deadlock condition detected */ -#define SOL_ENOLCK 46 /* Record locks unavailable */ -#define SOL_ECANCELED 47 /* Cancellation of oper. happened */ -#define SOL_ENOTSUP 48 /* Attempt of unsupported operation */ -#define SOL_EDQUOT 49 /* Users disk quota exceeded */ -#define SOL_EBADE 50 /* Invalid exchange */ -#define SOL_EBADR 51 /* Request descriptor was invalid */ -#define SOL_EXFULL 52 /* Full exchange */ -#define SOL_ENOANO 53 /* ano does not exist */ -#define SOL_EBADRQC 54 /* Req code was invalid */ -#define SOL_EBADSLT 55 /* Bad slot number */ -#define SOL_EDEADLOCK 56 /* Deadlock in fs error */ -#define SOL_EBFONT 57 /* Font file format invalid */ -/* YOW, I LOVE SYSV STREAMS!!!! */ -#define SOL_ENOSTR 60 /* Stream-op on non-stream dev */ -#define SOL_ENODATA 61 /* No data avail at this time */ -#define SOL_ETIME 62 /* Expiration of time occurred */ -#define SOL_ENOSR 63 /* Streams resources exhausted */ -#define SOL_ENONET 64 /* No network connected */ -#define SOL_ENOPKG 65 /* Non-installed package */ -#define SOL_EREMOTE 66 /* Object was on remote machine */ -#define SOL_ENOLINK 67 /* Cut link */ -#define SOL_EADV 68 /* Error in advertise */ -#define SOL_ESRMNT 69 /* Some magic srmount problem */ -#define SOL_ECOMM 70 /* During send, comm error occurred */ -#define SOL_EPROTO 71 /* Protocol botch */ -#define SOL_EMULTIHOP 74 /* Multihop attempted */ -#define SOL_EBADMSG 77 /* Message was unreadable */ -#define SOL_ENAMETOOLONG 78 /* Too long of a path name */ -#define SOL_EOVERFLOW 79 /* Data type too small for datum */ -#define SOL_ENOTUNIQ 80 /* Logical name was not unique */ -#define SOL_EBADFD 81 /* Op cannot be performed on fd */ -#define SOL_EREMCHG 82 /* Remote address is now different */ -#define SOL_ELIBACC 83 /* Shared lib could not be accessed */ -#define SOL_ELIBBAD 84 /* ShLib is corrupted in some way */ -#define SOL_ELIBSCN 85 /* A.out ShLib problems */ -#define SOL_ELIBMAX 86 /* Exceeded ShLib linkage limit */ -#define SOL_ELIBEXEC 87 /* Execution of ShLib attempted */ -#define SOL_EILSEQ 88 /* Bad byte sequence found */ -#define SOL_ENOSYS 89 /* Invalid filesystem operation */ -#define SOL_ELOOP 90 /* Detected loop in symbolic links */ -#define SOL_ERESTART 91 /* System call is restartable */ -#define SOL_ESTRPIPE 92 /* Do not sleep in head of stream */ -#define SOL_ENOTEMPTY 93 /* Rmdir of non-empty directory */ -#define SOL_EUSERS 94 /* Over abundance of users for ufs */ -#define SOL_ENOTSOCK 95 /* Sock-op on non-sock */ -#define SOL_EDESTADDRREQ 96 /* No dest addr given, but needed */ -#define SOL_EMSGSIZE 97 /* Msg too big */ -#define SOL_EPROTOTYPE 98 /* Bad socket protocol */ -#define SOL_ENOPROTOOPT 99 /* Unavailable protocol */ -#define SOL_EPROTONOSUPPORT 120 /* Unsupported protocol */ -#define SOL_ESOCKTNOSUPPORT 121 /* Unsupported socket type */ -#define SOL_EOPNOTSUPP 122 /* Unsupported sock-op */ -#define SOL_EPFNOSUPPORT 123 /* Unsupported protocol family */ -#define SOL_EAFNOSUPPORT 124 /* Unsup addr family for protocol */ -#define SOL_EADDRINUSE 125 /* Req addr is already in use */ -#define SOL_EADDRNOTAVAIL 126 /* Req addr not available right now */ -#define SOL_ENETDOWN 127 /* Your subnet is on fire */ -#define SOL_ENETUNREACH 128 /* Someone playing with gateway and */ - /* did not tell you he was going to */ -#define SOL_ENETRESET 129 /* Buy less-buggy ethernet cards */ -#define SOL_ECONNABORTED 130 /* Aborted connection due to sw */ -#define SOL_ECONNRESET 131 /* Your peers reset your connection */ -#define SOL_ENOBUFS 132 /* No buffer space available */ -#define SOL_EISCONN 133 /* Connect on already connected */ - /* socket attempted */ -#define SOL_ENOTCONN 134 /* Comm on non-connected socket */ -#define SOL_ESHUTDOWN 143 /* Op attempted after sock-shutdown */ -#define SOL_ETOOMANYREFS 144 /* Reference limit exceeded */ -#define SOL_ETIMEDOUT 145 /* Timed out connection */ -#define SOL_ECONNREFUSED 146 /* Connection refused by remote host*/ -#define SOL_EHOSTDOWN 147 /* Remote host is up in flames */ -#define SOL_EHOSTUNREACH 148 /* Make a left at Easton Ave..... */ -#define SOL_EWOULDBLOCK EAGAIN /* Just an alias */ -#define SOL_EALREADY 149 /* Operation is already occurring */ -#define SOL_EINPROGRESS 150 /* Operation is happening now */ -#define SOL_ESTALE 151 /* Fungus growth on NFS file handle */ - -#endif /* !(_SPARC64_SOLERRNO_H) */ diff --git a/include/asm-sparc64/svr4.h b/include/asm-sparc64/svr4.h deleted file mode 100644 index c96d5f116e1c..000000000000 --- a/include/asm-sparc64/svr4.h +++ /dev/null @@ -1,120 +0,0 @@ -/* Solaris/SPARC constants and definitions -- - * (C) 1996 Miguel de Icaza - * - * This file is not meant to be included by user level applications - * but the solaris syscall emulator - */ - -#ifndef _SPARC64_SVR4_H -#define _SPARC64_SVR4_H - -/* Signals as used by svr4 */ -typedef struct { /* signal set type */ - uint sigbits[4]; -} svr4_sigset_t; - -/* Values for siginfo.code */ -#define SVR4_SINOINFO 32767 -/* Siginfo, sucker expects bunch of information on those parameters */ -typedef union { - char total_size [128]; - struct { - int signo; - int code; - int error; - union { - } data; - } siginfo; -} svr4_siginfo_t; - -/* Context definition */ - -/* Location of the user stored registers into a greg_t */ -enum { - SVR4_PSR, SVR4_PC, SVR4_NPC, SVR4_Y, - SVR4_G1, SVR4_G2, SVR4_G3, SVR4_G4, - SVR4_G5, SVR4_G6, SVR4_G7, SVR4_O0, - SVR4_O1, SVR4_O2, SVR4_O3, SVR4_O4, - SVR4_O5, SVR4_O6, SVR4_O7 -}; - -/* sizeof (regs) / sizeof (greg_t), defined in the ABI */ -#define SVR4_NREGS 19 -#define SVR4_MAXWIN 31 - -typedef struct { - u32 rwin_lo[8]; - u32 rwin_in[8]; -} svr4_rwindow_t; - -typedef struct { - int count; - u32 winptr [SVR4_MAXWIN]; /* pointer to the windows */ - - svr4_rwindow_t win[SVR4_MAXWIN]; /* the windows */ -} svr4_gwindows_t; - -typedef int svr4_gregset_t[SVR4_NREGS]; - -typedef struct { - u64 fpu_regs[32]; - u32 fp_q; - u32 fp_fsr; - u_char fp_nqel; - u_char fp_nqsize; - u_char inuse; /* if fpu is in use */ -} svr4_fregset_t; - -typedef struct { - u32 id; /* if this holds "xrs" string => ptr is valid */ - u32 ptr; -} svr4_xrs_t; - -/* Machine dependent context */ -typedef struct { - svr4_gregset_t greg; /* registers 0..19 (see top) */ - u32 gwin; /* may point to register windows */ - svr4_fregset_t freg; /* floating point registers */ - svr4_xrs_t xrs; /* mhm? */ - int pad[19]; -} svr4_mcontext_t; - -/* flags for stack_t.flags */ -enum svr4_stack_flags { - SVR4_SS_ONSTACK, - SVR4_SS_DISABLE, -}; - -/* signal stack execution place, unsupported */ -typedef struct svr4_stack_t { - u32 sp; - int size; - int flags; -} svr4_stack_t; - -/* Context used by getcontext and setcontext */ -typedef struct svr4_ucontext_t { - u32 flags; /* context flags, indicate what is loaded */ - u32 link; - svr4_sigset_t sigmask; - svr4_stack_t stack; - svr4_mcontext_t mcontext; - int pad[23]; -} svr4_ucontext_t; - -/* windows hold the windows as they were at signal time, - * ucontext->mcontext holds a pointer to them. - * addresses for uc and si are passed as parameters to svr4 signal - * handler - */ - -/* This is the signal frame that is passed to the signal handler */ -typedef struct { - svr4_gwindows_t gw; /* windows */ - svr4_ucontext_t uc; /* machine context */ - svr4_siginfo_t si; /* siginfo */ -} svr4_signal_frame_t; - -#define SVR4_SF_ALIGNED (((sizeof (svr4_signal_frame_t) + 7) & (~7))) - -#endif /* include control */ diff --git a/include/asm-sparc64/termios.h b/include/asm-sparc64/termios.h index ef527211f8a8..cacbea171ad7 100644 --- a/include/asm-sparc64/termios.h +++ b/include/asm-sparc64/termios.h @@ -33,11 +33,6 @@ struct ltchars { }; #endif /* __KERNEL__ */ -struct sunos_ttysize { - int st_lines; /* Lines on the terminal */ - int st_columns; /* Columns on the terminal */ -}; - struct winsize { unsigned short ws_row; unsigned short ws_col; diff --git a/include/asm-sparc64/ttable.h b/include/asm-sparc64/ttable.h index bbb9c8f13d61..7208a777750e 100644 --- a/include/asm-sparc64/ttable.h +++ b/include/asm-sparc64/ttable.h @@ -99,14 +99,6 @@ or %l7, %lo(systbl), %l7; \ nop; nop; -#define INDIRECT_SOLARIS_SYSCALL(num) \ - sethi %hi(109f), %g7; \ - ba,pt %xcc, etrap; \ -109: or %g7, %lo(109b), %g7; \ - ba,pt %xcc, tl0_solaris + 0xc; \ - mov num, %g1; \ - nop;nop;nop; - #define TRAP_UTRAP(handler,lvl) \ mov handler, %g3; \ ba,pt %xcc, utrap_trap; \ @@ -117,11 +109,6 @@ nop; \ nop; -#ifdef CONFIG_SUNOS_EMUL -#define SUNOS_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sunos_sys_table) -#else -#define SUNOS_SYSCALL_TRAP TRAP(sunos_syscall) -#endif #ifdef CONFIG_COMPAT #define LINUX_32BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall32, sys_call_table32) #else @@ -130,11 +117,6 @@ #define LINUX_64BIT_SYSCALL_TRAP SYSCALL_TRAP(linux_sparc_syscall, sys_call_table64) #define GETCC_TRAP TRAP(getcc) #define SETCC_TRAP TRAP(setcc) -#ifdef CONFIG_SOLARIS_EMUL -#define SOLARIS_SYSCALL_TRAP TRAP(solaris_sparc_syscall) -#else -#define SOLARIS_SYSCALL_TRAP TRAP(solaris_syscall) -#endif #define BREAKPOINT_TRAP TRAP(breakpoint_trap) #ifdef CONFIG_TRACE_IRQFLAGS diff --git a/include/asm-sparc64/unistd.h b/include/asm-sparc64/unistd.h index 77559da0ea3f..13be4453a1f0 100644 --- a/include/asm-sparc64/unistd.h +++ b/include/asm-sparc64/unistd.h @@ -338,16 +338,6 @@ #define NR_SYSCALLS 317 #ifdef __KERNEL__ -/* sysconf options, for SunOS compatibility */ -#define _SC_ARG_MAX 1 -#define _SC_CHILD_MAX 2 -#define _SC_CLK_TCK 3 -#define _SC_NGROUPS_MAX 4 -#define _SC_OPEN_MAX 5 -#define _SC_JOB_CONTROL 6 -#define _SC_SAVED_IDS 7 -#define _SC_VERSION 8 - #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR #define __ARCH_WANT_STAT64 diff --git a/include/asm-sparc64/user.h b/include/asm-sparc64/user.h index 02b138943837..29fc6e906c29 100644 --- a/include/asm-sparc64/user.h +++ b/include/asm-sparc64/user.h @@ -1,60 +1 @@ -/* $Id: user.h,v 1.1 1996/12/26 14:22:44 davem Exp $ - * asm-sparc64/user.h: Core file definitions for the Sparc. - * - * Keep in sync with reg.h. Actually, we could get rid of this - * one, since we won't a.out core dump that much anyways - miguel. - * Copyright (C) 1995 (davem@caip.rutgers.edu) - */ -#ifndef _SPARC64_USER_H -#define _SPARC64_USER_H - -#include -struct sunos_regs { - unsigned int psr, pc, npc, y; - unsigned int regs[15]; -}; - -struct sunos_fpqueue { - unsigned int *addr; - unsigned int inst; -}; - -struct sunos_fp { - union { - unsigned int regs[32]; - double reg_dbls[16]; - } fregs; - unsigned int fsr; - unsigned int flags; - unsigned int extra; - unsigned int fpq_count; - struct sunos_fpqueue fpq[16]; -}; - -struct sunos_fpu { - struct sunos_fp fpstatus; -}; - -/* The SunOS core file header layout. */ -struct user { - unsigned int magic; - unsigned int len; - struct sunos_regs regs; - struct exec uexec; - int signal; - size_t u_tsize; /* all of these in bytes! */ - size_t u_dsize; - size_t u_ssize; - char u_comm[17]; - struct sunos_fpu fpu; - unsigned int sigcode; /* Special sigcontext subcode, if any */ -}; - -#define NBPG PAGE_SIZE /* XXX 4096 maybe? */ -#define UPAGES 1 -#define HOST_TEXT_START_ADDR (u.start_code) -#define HOST_DATA_START_ADDR (u.start_data) -#define HOST_STACK_END_ADDR (u.start_stack + u.u_ssize * NBPG) -#define SUNOS_CORE_MAGIC 0x080456 - -#endif /* !(_SPARC64_USER_H) */ +#include diff --git a/net/core/sock.c b/net/core/sock.c index 54c836a2216b..bf6f83e48e87 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -450,15 +450,6 @@ int sock_setsockopt(struct socket *sock, int level, int optname, * Options without arguments */ -#ifdef SO_DONTLINGER /* Compatibility item... */ - if (optname == SO_DONTLINGER) { - lock_sock(sk); - sock_reset_flag(sk, SOCK_LINGER); - release_sock(sk); - return 0; - } -#endif - if (optname == SO_BINDTODEVICE) return sock_bindtodevice(sk, optval, optlen); -- cgit v1.2.3 From 1fb7c6e4cba35b5e7cef88b58d0a2ad164d801a5 Mon Sep 17 00:00:00 2001 From: Jesper Juhl Date: Mon, 21 Apr 2008 22:12:32 +0000 Subject: Correct a few trivial tree details in Documentation/SubmittingPatches Correct maintainer name and URL. Signed-off-by: Jesper Juhl --- Documentation/SubmittingPatches | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches index 1fc4e7144dce..9c93a03ea33b 100644 --- a/Documentation/SubmittingPatches +++ b/Documentation/SubmittingPatches @@ -183,7 +183,7 @@ Even if the maintainer did not respond in step #4, make sure to ALWAYS copy the maintainer when you change their code. For small patches you may want to CC the Trivial Patch Monkey -trivial@kernel.org managed by Adrian Bunk; which collects "trivial" +trivial@kernel.org managed by Jesper Juhl; which collects "trivial" patches. Trivial patches must qualify for one of the following rules: Spelling fixes in documentation Spelling fixes which could break grep(1) @@ -196,7 +196,7 @@ patches. Trivial patches must qualify for one of the following rules: since people copy, as long as it's trivial) Any fix by the author/maintainer of the file (ie. patch monkey in re-transmission mode) -URL: +URL: -- cgit v1.2.3 From fda6ab8bbe2a2276d491aed1358975c8c516a243 Mon Sep 17 00:00:00 2001 From: Cyril Brulebois Date: Mon, 21 Apr 2008 22:19:05 +0000 Subject: Documentation: Remove last references to BitKeeper. Remove BitKeeper from dontdiff. Point to the klibc git repository instead of old BitKeeper ones. Signed-off-by: Cyril Brulebois Signed-off-by: Jesper Juhl --- Documentation/dontdiff | 1 - Documentation/early-userspace/README | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/dontdiff b/Documentation/dontdiff index c09a96b99354..354aec047c0e 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -47,7 +47,6 @@ .mm 53c700_d.h 53c8xx_d.h* -BitKeeper COPYING CREDITS CVS diff --git a/Documentation/early-userspace/README b/Documentation/early-userspace/README index 766d320c8eb6..e35d83052192 100644 --- a/Documentation/early-userspace/README +++ b/Documentation/early-userspace/README @@ -89,8 +89,8 @@ the 2.7 era (it missed the boat for 2.5). You can obtain somewhat infrequent snapshots of klibc from ftp://ftp.kernel.org/pub/linux/libs/klibc/ -For active users, you are better off using the klibc BitKeeper -repositories, at http://klibc.bkbits.net/ +For active users, you are better off using the klibc git +repository, at http://git.kernel.org/?p=libs/klibc/klibc.git The standalone klibc distribution currently provides three components, in addition to the klibc library: -- cgit v1.2.3 From 58da495065134b45799bd02988ab658c3da6af25 Mon Sep 17 00:00:00 2001 From: Pavel Machek Date: Mon, 21 Apr 2008 22:23:30 +0000 Subject: firmware_sample_driver.c: fix coding style Fix coding style in firmware_sample_driver... Signed-off-by: Pavel Machek Signed-off-by: Jesper Juhl --- Documentation/firmware_class/firmware_sample_driver.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/firmware_class/firmware_sample_driver.c b/Documentation/firmware_class/firmware_sample_driver.c index 6865cbe075ec..600cdd9ea7db 100644 --- a/Documentation/firmware_class/firmware_sample_driver.c +++ b/Documentation/firmware_class/firmware_sample_driver.c @@ -34,8 +34,7 @@ static void sample_probe_default(void) const struct firmware *fw_entry; printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n"); - if(request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0) - { + if (request_firmware(&fw_entry, "sample_driver_fw", &ghost_device)!=0) { printk(KERN_ERR "firmware_sample_driver: Firmware not available\n"); return; @@ -56,8 +55,7 @@ static void sample_probe_specific(void) printk(KERN_INFO "firmware_sample_driver: a ghost device got inserted :)\n"); - if(request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0) - { + if (request_firmware(NULL, "sample_driver_fw", &ghost_device)!=0) { printk(KERN_ERR "firmware_sample_driver: Firmware load failed\n"); return; @@ -70,7 +68,7 @@ static void sample_probe_specific(void) } static void sample_probe_async_cont(const struct firmware *fw, void *context) { - if(!fw){ + if (!fw) { printk(KERN_ERR "firmware_sample_driver: firmware load failed\n"); return; @@ -88,9 +86,8 @@ static void sample_probe_async(void) "sample_driver_fw", &ghost_device, "my device pointer", sample_probe_async_cont); - if(error){ - printk(KERN_ERR - "firmware_sample_driver:" + if (error) { + printk(KERN_ERR "firmware_sample_driver:" " request_firmware_nowait failed\n"); } } @@ -105,6 +102,7 @@ static int sample_init(void) sample_probe_async(); return 0; } + static void __exit sample_exit(void) { } -- cgit v1.2.3 From c0d1f29534f2bd6c5992831eb0f648522e9b0204 Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Mon, 21 Apr 2008 22:44:50 +0000 Subject: DOCUMENTATION: Use newer DEFINE_SPINLOCK macro in docs. Signed-off-by: Robert P. J. Day Signed-off-by: Jesper Juhl --- Documentation/DocBook/kernel-locking.tmpl | 4 ++-- Documentation/block/biodoc.txt | 2 +- Documentation/cli-sti-removal.txt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/kernel-locking.tmpl b/Documentation/DocBook/kernel-locking.tmpl index 2e9d6b41f034..22ebd27a257e 100644 --- a/Documentation/DocBook/kernel-locking.tmpl +++ b/Documentation/DocBook/kernel-locking.tmpl @@ -854,7 +854,7 @@ The change is shown below, in standard patch format: the }; -static DEFINE_MUTEX(cache_lock); -+static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED; ++static DEFINE_SPINLOCK(cache_lock); static LIST_HEAD(cache); static unsigned int cache_num = 0; #define MAX_CACHE_SIZE 10 @@ -1238,7 +1238,7 @@ Here is the "lock-per-object" implementation: - int popularity; }; - static spinlock_t cache_lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(cache_lock); @@ -77,6 +84,7 @@ obj->id = id; obj->popularity = 0; diff --git a/Documentation/block/biodoc.txt b/Documentation/block/biodoc.txt index 93f223b9723f..4dbb8be1c991 100644 --- a/Documentation/block/biodoc.txt +++ b/Documentation/block/biodoc.txt @@ -1097,7 +1097,7 @@ lock themselves, if required. Drivers that explicitly used the io_request_lock for serialization need to be modified accordingly. Usually it's as easy as adding a global lock: - static spinlock_t my_driver_lock = SPIN_LOCK_UNLOCKED; + static DEFINE_SPINLOCK(my_driver_lock); and passing the address to that lock to blk_init_queue(). diff --git a/Documentation/cli-sti-removal.txt b/Documentation/cli-sti-removal.txt index 0223c9d20331..60932b02fcb3 100644 --- a/Documentation/cli-sti-removal.txt +++ b/Documentation/cli-sti-removal.txt @@ -43,7 +43,7 @@ would execute while the cli()-ed section is executing. but from now on a more direct method of locking has to be used: - spinlock_t driver_lock = SPIN_LOCK_UNLOCKED; + DEFINE_SPINLOCK(driver_lock); struct driver_data; irq_handler (...) -- cgit v1.2.3 From 838cb6aba4cebcf4fcd06b90e2adf890bef884ac Mon Sep 17 00:00:00 2001 From: "Robert P. J. Day" Date: Mon, 21 Apr 2008 22:57:50 +0000 Subject: DOC: A couple corrections and clarifications in USB doc. A couple of corrections and clarifications in USB documentation. Signed-off-by: Robert P. J. Day Signed-off-by: Jesper Juhl --- Documentation/DocBook/writing_usb_driver.tmpl | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/writing_usb_driver.tmpl b/Documentation/DocBook/writing_usb_driver.tmpl index d4188d4ff535..eeff19ca831b 100644 --- a/Documentation/DocBook/writing_usb_driver.tmpl +++ b/Documentation/DocBook/writing_usb_driver.tmpl @@ -100,8 +100,8 @@ useful documents, at the USB home page (see Resources). An excellent introduction to the Linux USB subsystem can be found at the USB Working Devices List (see Resources). It explains how the Linux USB subsystem is - structured and introduces the reader to the concept of USB urbs, which - are essential to USB drivers. + structured and introduces the reader to the concept of USB urbs + (USB Request Blocks), which are essential to USB drivers. The first thing a Linux USB driver needs to do is register itself with @@ -162,8 +162,8 @@ static int __init usb_skel_init(void) module_init(usb_skel_init); - When the driver is unloaded from the system, it needs to unregister - itself with the USB subsystem. This is done with the usb_unregister + When the driver is unloaded from the system, it needs to deregister + itself with the USB subsystem. This is done with the usb_deregister function: @@ -232,7 +232,7 @@ static int skel_probe(struct usb_interface *interface, were passed to the USB subsystem will be called from a user program trying to talk to the device. The first function called will be open, as the program tries to open the device for I/O. We increment our private usage - count and save off a pointer to our internal structure in the file + count and save a pointer to our internal structure in the file structure. This is done so that future calls to file operations will enable the driver to determine which device the user is addressing. All of this is done with the following code: @@ -252,8 +252,8 @@ file->private_data = dev; send to the device based on the size of the write urb it has created (this size depends on the size of the bulk out end point that the device has). Then it copies the data from user space to kernel space, points the urb to - the data and submits the urb to the USB subsystem. This can be shown in - he following code: + the data and submits the urb to the USB subsystem. This can be seen in + the following code: /* we can only write as much as 1 urb will hold */ -- cgit v1.2.3 From 71d54f3855b4ca98559e8782350336ec2433cc24 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 15 Apr 2008 11:36:19 +0100 Subject: [MTD] [NAND] S3C2410 Large page NAND support This adds support for using large page NAND devices with the S3C24XX NAND controller. This also adds the file Documentation/arm/Samsung-S3C24XX/NAND.txt to describe the differences. Signed-off-by: Ben Dooks Signed-off-by: David Woodhouse --- Documentation/arm/Samsung-S3C24XX/NAND.txt | 30 ++++++++++++++++++++ Documentation/arm/Samsung-S3C24XX/Overview.txt | 2 ++ drivers/mtd/nand/s3c2410.c | 38 ++++++++++++++++++++++---- 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 Documentation/arm/Samsung-S3C24XX/NAND.txt (limited to 'Documentation') diff --git a/Documentation/arm/Samsung-S3C24XX/NAND.txt b/Documentation/arm/Samsung-S3C24XX/NAND.txt new file mode 100644 index 000000000000..bc478a3409b8 --- /dev/null +++ b/Documentation/arm/Samsung-S3C24XX/NAND.txt @@ -0,0 +1,30 @@ + S3C24XX NAND Support + ==================== + +Introduction +------------ + +Small Page NAND +--------------- + +The driver uses a 512 byte (1 page) ECC code for this setup. The +ECC code is not directly compatible with the default kernel ECC +code, so the driver enforces its own OOB layout and ECC parameters + +Large Page NAND +--------------- + +The driver is capable of handling NAND flash with a 2KiB page +size, with support for hardware ECC generation and correction. + +Unlike the 512byte page mode, the driver generates ECC data for +each 256 byte block in an 2KiB page. This means that more than +one error in a page can be rectified. It also means that the +OOB layout remains the default kernel layout for these flashes. + + +Document Author +--------------- + +Ben Dooks, Copyright 2007 Simtec Electronics + diff --git a/Documentation/arm/Samsung-S3C24XX/Overview.txt b/Documentation/arm/Samsung-S3C24XX/Overview.txt index c31b76fa66c4..d04e1e30c47f 100644 --- a/Documentation/arm/Samsung-S3C24XX/Overview.txt +++ b/Documentation/arm/Samsung-S3C24XX/Overview.txt @@ -156,6 +156,8 @@ NAND controller. If there are any problems the latest linux-mtd code can be found from http://www.linux-mtd.infradead.org/ + For more information see Documentation/arm/Samsung-S3C24XX/NAND.txt + Serial ------ diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 8557c68dbb42..15397e0f3965 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -472,7 +472,7 @@ static int s3c2440_nand_calculate_ecc(struct mtd_info *mtd, const u_char *dat, u ecc_code[1] = ecc >> 8; ecc_code[2] = ecc >> 16; - pr_debug("%s: returning ecc %06lx\n", __func__, ecc); + pr_debug("%s: returning ecc %06lx\n", __func__, ecc & 0xffffff); return 0; } @@ -643,9 +643,6 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, chip->ecc.calculate = s3c2410_nand_calculate_ecc; chip->ecc.correct = s3c2410_nand_correct_data; chip->ecc.mode = NAND_ECC_HW; - chip->ecc.size = 512; - chip->ecc.bytes = 3; - chip->ecc.layout = &nand_hw_eccoob; switch (info->cpu_type) { case TYPE_S3C2410: @@ -669,6 +666,34 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, } } +/* s3c2410_nand_update_chip + * + * post-probe chip update, to change any items, such as the + * layout for large page nand + */ + +static void s3c2410_nand_update_chip(struct s3c2410_nand_info *info, + struct s3c2410_nand_mtd *nmtd) +{ + struct nand_chip *chip = &nmtd->chip; + + printk("%s: chip %p: %d\n", __func__, chip, chip->page_shift); + + if (hardware_ecc) { + /* change the behaviour depending on wether we are using + * the large or small page nand device */ + + if (chip->page_shift > 10) { + chip->ecc.size = 256; + chip->ecc.bytes = 3; + } else { + chip->ecc.size = 512; + chip->ecc.bytes = 3; + chip->ecc.layout = &nand_hw_eccoob; + } + } +} + /* s3c2410_nand_probe * * called by device layer when it finds a device matching @@ -775,9 +800,12 @@ static int s3c24xx_nand_probe(struct platform_device *pdev, s3c2410_nand_init_chip(info, nmtd, sets); - nmtd->scan_res = nand_scan(&nmtd->mtd, (sets) ? sets->nr_chips : 1); + nmtd->scan_res = nand_scan_ident(&nmtd->mtd, + (sets) ? sets->nr_chips : 1); if (nmtd->scan_res == 0) { + s3c2410_nand_update_chip(info, nmtd); + nand_scan_tail(&nmtd->mtd); s3c2410_nand_add_partition(info, nmtd, sets); } -- cgit v1.2.3 From 2d4d4864ac08caff5c204a752bd004eed4f08760 Mon Sep 17 00:00:00 2001 From: Ram Pai Date: Thu, 27 Mar 2008 13:06:25 +0100 Subject: [patch 6/7] vfs: mountinfo: add /proc//mountinfo [mszeredi@suse.cz] rewrite and split big patch into managable chunks /proc/mounts in its current form lacks important information: - propagation state - root of mount for bind mounts - the st_dev value used within the filesystem - identifier for each mount and it's parent It also suffers from the following problems: - not easily extendable - ambiguity of mountpoints within a chrooted environment - doesn't distinguish between filesystem dependent and independent options - doesn't distinguish between per mount and per super block options This patch introduces /proc//mountinfo which attempts to address all these deficiencies. Code shared between /proc//mounts and /proc//mountinfo is extracted into separate functions. Thanks to Al Viro for the help in getting the design right. Signed-off-by: Ram Pai Signed-off-by: Miklos Szeredi Signed-off-by: Al Viro --- Documentation/filesystems/proc.txt | 32 ++++++++++ fs/namespace.c | 119 ++++++++++++++++++++++++++++++------- fs/proc/base.c | 15 +++++ include/linux/mnt_namespace.h | 1 + 4 files changed, 144 insertions(+), 23 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 518ebe609e2b..2cd920f92e5e 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -43,6 +43,7 @@ Table of Contents 2.13 /proc//oom_score - Display current oom-killer score 2.14 /proc//io - Display the IO accounting fields 2.15 /proc//coredump_filter - Core dump filtering settings + 2.16 /proc//mountinfo - Information about mounts ------------------------------------------------------------------------------ Preface @@ -2348,4 +2349,35 @@ For example: $ echo 0x7 > /proc/self/coredump_filter $ ./some_program +2.16 /proc//mountinfo - Information about mounts +-------------------------------------------------------- + +This file contains lines of the form: + +36 35 98:0 /mnt1 /mnt2 rw,noatime master:1 - ext3 /dev/root rw,errors=continue +(1)(2)(3) (4) (5) (6) (7) (8) (9) (10) (11) + +(1) mount ID: unique identifier of the mount (may be reused after umount) +(2) parent ID: ID of parent (or of self for the top of the mount tree) +(3) major:minor: value of st_dev for files on filesystem +(4) root: root of the mount within the filesystem +(5) mount point: mount point relative to the process's root +(6) mount options: per mount options +(7) optional fields: zero or more fields of the form "tag[:value]" +(8) separator: marks the end of the optional fields +(9) filesystem type: name of filesystem of the form "type[.subtype]" +(10) mount source: filesystem specific information or "none" +(11) super options: per super block options + +Parsers should ignore all unrecognised optional fields. Currently the +possible optional fields are: + +shared:X mount is shared in peer group X +master:X mount is slave to peer group X +unbindable mount is unbindable + +For more information on mount propagation see: + + Documentation/filesystems/sharedsubtree.txt + ------------------------------------------------------------------------------ diff --git a/fs/namespace.c b/fs/namespace.c index dfdf51e81c1c..c807b8d5f891 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -746,20 +746,30 @@ static void m_stop(struct seq_file *m, void *v) up_read(&namespace_sem); } -static int show_vfsmnt(struct seq_file *m, void *v) +struct proc_fs_info { + int flag; + const char *str; +}; + +static void show_sb_opts(struct seq_file *m, struct super_block *sb) { - struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); - int err = 0; - static struct proc_fs_info { - int flag; - char *str; - } fs_info[] = { + static const struct proc_fs_info fs_info[] = { { MS_SYNCHRONOUS, ",sync" }, { MS_DIRSYNC, ",dirsync" }, { MS_MANDLOCK, ",mand" }, { 0, NULL } }; - static struct proc_fs_info mnt_info[] = { + const struct proc_fs_info *fs_infop; + + for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { + if (sb->s_flags & fs_infop->flag) + seq_puts(m, fs_infop->str); + } +} + +static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt) +{ + static const struct proc_fs_info mnt_info[] = { { MNT_NOSUID, ",nosuid" }, { MNT_NODEV, ",nodev" }, { MNT_NOEXEC, ",noexec" }, @@ -768,27 +778,37 @@ static int show_vfsmnt(struct seq_file *m, void *v) { MNT_RELATIME, ",relatime" }, { 0, NULL } }; - struct proc_fs_info *fs_infop; + const struct proc_fs_info *fs_infop; + + for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) { + if (mnt->mnt_flags & fs_infop->flag) + seq_puts(m, fs_infop->str); + } +} + +static void show_type(struct seq_file *m, struct super_block *sb) +{ + mangle(m, sb->s_type->name); + if (sb->s_subtype && sb->s_subtype[0]) { + seq_putc(m, '.'); + mangle(m, sb->s_subtype); + } +} + +static int show_vfsmnt(struct seq_file *m, void *v) +{ + struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); + int err = 0; struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); seq_putc(m, ' '); seq_path(m, &mnt_path, " \t\n\\"); seq_putc(m, ' '); - mangle(m, mnt->mnt_sb->s_type->name); - if (mnt->mnt_sb->s_subtype && mnt->mnt_sb->s_subtype[0]) { - seq_putc(m, '.'); - mangle(m, mnt->mnt_sb->s_subtype); - } + show_type(m, mnt->mnt_sb); seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw"); - for (fs_infop = fs_info; fs_infop->flag; fs_infop++) { - if (mnt->mnt_sb->s_flags & fs_infop->flag) - seq_puts(m, fs_infop->str); - } - for (fs_infop = mnt_info; fs_infop->flag; fs_infop++) { - if (mnt->mnt_flags & fs_infop->flag) - seq_puts(m, fs_infop->str); - } + show_sb_opts(m, mnt->mnt_sb); + show_mnt_opts(m, mnt); if (mnt->mnt_sb->s_op->show_options) err = mnt->mnt_sb->s_op->show_options(m, mnt); seq_puts(m, " 0 0\n"); @@ -802,6 +822,59 @@ const struct seq_operations mounts_op = { .show = show_vfsmnt }; +static int show_mountinfo(struct seq_file *m, void *v) +{ + struct proc_mounts *p = m->private; + struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); + struct super_block *sb = mnt->mnt_sb; + struct path mnt_path = { .dentry = mnt->mnt_root, .mnt = mnt }; + struct path root = p->root; + int err = 0; + + seq_printf(m, "%i %i %u:%u ", mnt->mnt_id, mnt->mnt_parent->mnt_id, + MAJOR(sb->s_dev), MINOR(sb->s_dev)); + seq_dentry(m, mnt->mnt_root, " \t\n\\"); + seq_putc(m, ' '); + seq_path_root(m, &mnt_path, &root, " \t\n\\"); + if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { + /* + * Mountpoint is outside root, discard that one. Ugly, + * but less so than trying to do that in iterator in a + * race-free way (due to renames). + */ + return SEQ_SKIP; + } + seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); + show_mnt_opts(m, mnt); + + /* Tagged fields ("foo:X" or "bar") */ + if (IS_MNT_SHARED(mnt)) + seq_printf(m, " shared:%i", mnt->mnt_group_id); + if (IS_MNT_SLAVE(mnt)) + seq_printf(m, " master:%i", mnt->mnt_master->mnt_group_id); + if (IS_MNT_UNBINDABLE(mnt)) + seq_puts(m, " unbindable"); + + /* Filesystem specific data */ + seq_puts(m, " - "); + show_type(m, sb); + seq_putc(m, ' '); + mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none"); + seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw"); + show_sb_opts(m, sb); + if (sb->s_op->show_options) + err = sb->s_op->show_options(m, mnt); + seq_putc(m, '\n'); + return err; +} + +const struct seq_operations mountinfo_op = { + .start = m_start, + .next = m_next, + .stop = m_stop, + .show = show_mountinfo, +}; + static int show_vfsstat(struct seq_file *m, void *v) { struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); @@ -822,7 +895,7 @@ static int show_vfsstat(struct seq_file *m, void *v) /* file system type */ seq_puts(m, "with fstype "); - mangle(m, mnt->mnt_sb->s_type->name); + show_type(m, mnt->mnt_sb); /* optional statistics */ if (mnt->mnt_sb->s_op->show_stats) { diff --git a/fs/proc/base.c b/fs/proc/base.c index a04b3db7a296..c5e412a00b17 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -604,6 +604,19 @@ static const struct file_operations proc_mounts_operations = { .poll = mounts_poll, }; +static int mountinfo_open(struct inode *inode, struct file *file) +{ + return mounts_open_common(inode, file, &mountinfo_op); +} + +static const struct file_operations proc_mountinfo_operations = { + .open = mountinfo_open, + .read = seq_read, + .llseek = seq_lseek, + .release = mounts_release, + .poll = mounts_poll, +}; + static int mountstats_open(struct inode *inode, struct file *file) { return mounts_open_common(inode, file, &mountstats_op); @@ -2303,6 +2316,7 @@ static const struct pid_entry tgid_base_stuff[] = { LNK("root", root), LNK("exe", exe), REG("mounts", S_IRUGO, mounts), + REG("mountinfo", S_IRUGO, mountinfo), REG("mountstats", S_IRUSR, mountstats), #ifdef CONFIG_PROC_PAGE_MONITOR REG("clear_refs", S_IWUSR, clear_refs), @@ -2635,6 +2649,7 @@ static const struct pid_entry tid_base_stuff[] = { LNK("root", root), LNK("exe", exe), REG("mounts", S_IRUGO, mounts), + REG("mountinfo", S_IRUGO, mountinfo), #ifdef CONFIG_PROC_PAGE_MONITOR REG("clear_refs", S_IWUSR, clear_refs), REG("smaps", S_IRUGO, smaps), diff --git a/include/linux/mnt_namespace.h b/include/linux/mnt_namespace.h index c078aacc8116..830bbcd449d6 100644 --- a/include/linux/mnt_namespace.h +++ b/include/linux/mnt_namespace.h @@ -46,6 +46,7 @@ static inline void get_mnt_ns(struct mnt_namespace *ns) } extern const struct seq_operations mounts_op; +extern const struct seq_operations mountinfo_op; extern const struct seq_operations mountstats_op; #endif -- cgit v1.2.3 From 97e7e0f71d6d948c25f11f0a33878d9356d9579e Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Thu, 27 Mar 2008 13:06:26 +0100 Subject: [patch 7/7] vfs: mountinfo: show dominating group id Show peer group ID of nearest dominating group that has intersection with the mount's namespace. Signed-off-by: Miklos Szeredi Signed-off-by: Al Viro --- Documentation/filesystems/proc.txt | 6 +++++ fs/namespace.c | 9 +++++-- fs/pnode.c | 51 ++++++++++++++++++++++++++++++++++++++ fs/pnode.h | 1 + 4 files changed, 65 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index 2cd920f92e5e..2a99116edc47 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt @@ -2374,8 +2374,14 @@ possible optional fields are: shared:X mount is shared in peer group X master:X mount is slave to peer group X +propagate_from:X mount is slave and receives propagation from peer group X (*) unbindable mount is unbindable +(*) X is the closest dominant peer group under the process's root. If +X is the immediate master of the mount, or if there's no dominant peer +group under the same root, then only the "master:X" field is present +and not the "propagate_from:X" field. + For more information on mount propagation see: Documentation/filesystems/sharedsubtree.txt diff --git a/fs/namespace.c b/fs/namespace.c index c807b8d5f891..0505fb61aa74 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -850,8 +850,13 @@ static int show_mountinfo(struct seq_file *m, void *v) /* Tagged fields ("foo:X" or "bar") */ if (IS_MNT_SHARED(mnt)) seq_printf(m, " shared:%i", mnt->mnt_group_id); - if (IS_MNT_SLAVE(mnt)) - seq_printf(m, " master:%i", mnt->mnt_master->mnt_group_id); + if (IS_MNT_SLAVE(mnt)) { + int master = mnt->mnt_master->mnt_group_id; + int dom = get_dominating_id(mnt, &p->root); + seq_printf(m, " master:%i", master); + if (dom && dom != master) + seq_printf(m, " propagate_from:%i", dom); + } if (IS_MNT_UNBINDABLE(mnt)) seq_puts(m, " unbindable"); diff --git a/fs/pnode.c b/fs/pnode.c index d18d66491a01..8d5f392ec3d3 100644 --- a/fs/pnode.c +++ b/fs/pnode.c @@ -28,6 +28,57 @@ static inline struct vfsmount *next_slave(struct vfsmount *p) return list_entry(p->mnt_slave.next, struct vfsmount, mnt_slave); } +/* + * Return true if path is reachable from root + * + * namespace_sem is held, and mnt is attached + */ +static bool is_path_reachable(struct vfsmount *mnt, struct dentry *dentry, + const struct path *root) +{ + while (mnt != root->mnt && mnt->mnt_parent != mnt) { + dentry = mnt->mnt_mountpoint; + mnt = mnt->mnt_parent; + } + return mnt == root->mnt && is_subdir(dentry, root->dentry); +} + +static struct vfsmount *get_peer_under_root(struct vfsmount *mnt, + struct mnt_namespace *ns, + const struct path *root) +{ + struct vfsmount *m = mnt; + + do { + /* Check the namespace first for optimization */ + if (m->mnt_ns == ns && is_path_reachable(m, m->mnt_root, root)) + return m; + + m = next_peer(m); + } while (m != mnt); + + return NULL; +} + +/* + * Get ID of closest dominating peer group having a representative + * under the given root. + * + * Caller must hold namespace_sem + */ +int get_dominating_id(struct vfsmount *mnt, const struct path *root) +{ + struct vfsmount *m; + + for (m = mnt->mnt_master; m != NULL; m = m->mnt_master) { + struct vfsmount *d = get_peer_under_root(m, mnt->mnt_ns, root); + if (d) + return d->mnt_group_id; + } + + return 0; +} + static int do_make_slave(struct vfsmount *mnt) { struct vfsmount *peer_mnt = mnt, *master = mnt->mnt_master; diff --git a/fs/pnode.h b/fs/pnode.h index 973c3f825e7d..958665d662af 100644 --- a/fs/pnode.h +++ b/fs/pnode.h @@ -36,4 +36,5 @@ int propagate_mnt(struct vfsmount *, struct dentry *, struct vfsmount *, int propagate_umount(struct list_head *); int propagate_mount_busy(struct vfsmount *, int); void mnt_release_group_id(struct vfsmount *); +int get_dominating_id(struct vfsmount *mnt, const struct path *root); #endif /* _LINUX_PNODE_H */ -- cgit v1.2.3 From a3fa73bd0eea74c58315114c9fc3e913f6c26d61 Mon Sep 17 00:00:00 2001 From: James Lentini Date: Mon, 25 Feb 2008 12:20:13 -0500 Subject: Documentation: NFS/RDMA instructions for 2.6.25-rc1 Add some instructions for using the new NFS/RDMA features. Signed-off-by: James Lentini Cc: Roland Dreier Signed-off-by: J. Bruce Fields --- Documentation/filesystems/nfs-rdma.txt | 252 +++++++++++++++++++++++++++++++++ 1 file changed, 252 insertions(+) create mode 100644 Documentation/filesystems/nfs-rdma.txt (limited to 'Documentation') diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt new file mode 100644 index 000000000000..1ae34879574b --- /dev/null +++ b/Documentation/filesystems/nfs-rdma.txt @@ -0,0 +1,252 @@ +################################################################################ +# # +# NFS/RDMA README # +# # +################################################################################ + + Author: NetApp and Open Grid Computing + Date: February 25, 2008 + +Table of Contents +~~~~~~~~~~~~~~~~~ + - Overview + - Getting Help + - Installation + - Check RDMA and NFS Setup + - NFS/RDMA Setup + +Overview +~~~~~~~~ + + This document describes how to install and setup the Linux NFS/RDMA client + and server software. + + The NFS/RDMA client was first included in Linux 2.6.24. The NFS/RDMA server + was first included in the following release, Linux 2.6.25. + + In our testing, we have obtained excellent performance results (full 10Gbit + wire bandwidth at minimal client CPU) under many workloads. The code passes + the full Connectathon test suite and operates over both Infiniband and iWARP + RDMA adapters. + +Getting Help +~~~~~~~~~~~~ + + If you get stuck, you can ask questions on the + + nfs-rdma-devel@lists.sourceforge.net + + mailing list. + +Installation +~~~~~~~~~~~~ + + These instructions are a step by step guide to building a machine for + use with NFS/RDMA. + + - Install an RDMA device + + Any device supported by the drivers in drivers/infiniband/hw is acceptable. + + Testing has been performed using several Mellanox-based IB cards, the + Ammasso AMS1100 iWARP adapter, and the Chelsio cxgb3 iWARP adapter. + + - Install a Linux distribution and tools + + The first kernel release to contain both the NFS/RDMA client and server was + Linux 2.6.25 Therefore, a distribution compatible with this and subsequent + Linux kernel release should be installed. + + The procedures described in this document have been tested with + distributions from Red Hat's Fedora Project (http://fedora.redhat.com/). + + - Install nfs-utils-1.1.1 or greater on the client + + An NFS/RDMA mount point can only be obtained by using the mount.nfs + command in nfs-utils-1.1.1 or greater. To see which version of mount.nfs + you are using, type: + + > /sbin/mount.nfs -V + + If the version is less than 1.1.1 or the command does not exist, + then you will need to install the latest version of nfs-utils. + + Download the latest package from: + + http://www.kernel.org/pub/linux/utils/nfs + + Uncompress the package and follow the installation instructions. + + If you will not be using GSS and NFSv4, the installation process + can be simplified by disabling these features when running configure: + + > ./configure --disable-gss --disable-nfsv4 + + For more information on this see the package's README and INSTALL files. + + After building the nfs-utils package, there will be a mount.nfs binary in + the utils/mount directory. This binary can be used to initiate NFS v2, v3, + or v4 mounts. To initiate a v4 mount, the binary must be called mount.nfs4. + The standard technique is to create a symlink called mount.nfs4 to mount.nfs. + + NOTE: mount.nfs and therefore nfs-utils-1.1.1 or greater is only needed + on the NFS client machine. You do not need this specific version of + nfs-utils on the server. Furthermore, only the mount.nfs command from + nfs-utils-1.1.1 is needed on the client. + + - Install a Linux kernel with NFS/RDMA + + The NFS/RDMA client and server are both included in the mainline Linux + kernel version 2.6.25 and later. This and other versions of the 2.6 Linux + kernel can be found at: + + ftp://ftp.kernel.org/pub/linux/kernel/v2.6/ + + Download the sources and place them in an appropriate location. + + - Configure the RDMA stack + + Make sure your kernel configuration has RDMA support enabled. Under + Device Drivers -> InfiniBand support, update the kernel configuration + to enable InfiniBand support [NOTE: the option name is misleading. Enabling + InfiniBand support is required for all RDMA devices (IB, iWARP, etc.)]. + + Enable the appropriate IB HCA support (mlx4, mthca, ehca, ipath, etc.) or + iWARP adapter support (amso, cxgb3, etc.). + + If you are using InfiniBand, be sure to enable IP-over-InfiniBand support. + + - Configure the NFS client and server + + Your kernel configuration must also have NFS file system support and/or + NFS server support enabled. These and other NFS related configuration + options can be found under File Systems -> Network File Systems. + + - Build, install, reboot + + The NFS/RDMA code will be enabled automatically if NFS and RDMA + are turned on. The NFS/RDMA client and server are configured via the hidden + SUNRPC_XPRT_RDMA config option that depends on SUNRPC and INFINIBAND. The + value of SUNRPC_XPRT_RDMA will be: + + - N if either SUNRPC or INFINIBAND are N, in this case the NFS/RDMA client + and server will not be built + - M if both SUNRPC and INFINIBAND are on (M or Y) and at least one is M, + in this case the NFS/RDMA client and server will be built as modules + - Y if both SUNRPC and INFINIBAND are Y, in this case the NFS/RDMA client + and server will be built into the kernel + + Therefore, if you have followed the steps above and turned no NFS and RDMA, + the NFS/RDMA client and server will be built. + + Build a new kernel, install it, boot it. + +Check RDMA and NFS Setup +~~~~~~~~~~~~~~~~~~~~~~~~ + + Before configuring the NFS/RDMA software, it is a good idea to test + your new kernel to ensure that the kernel is working correctly. + In particular, it is a good idea to verify that the RDMA stack + is functioning as expected and standard NFS over TCP/IP and/or UDP/IP + is working properly. + + - Check RDMA Setup + + If you built the RDMA components as modules, load them at + this time. For example, if you are using a Mellanox Tavor/Sinai/Arbel + card: + + > modprobe ib_mthca + > modprobe ib_ipoib + + If you are using InfiniBand, make sure there is a Subnet Manager (SM) + running on the network. If your IB switch has an embedded SM, you can + use it. Otherwise, you will need to run an SM, such as OpenSM, on one + of your end nodes. + + If an SM is running on your network, you should see the following: + + > cat /sys/class/infiniband/driverX/ports/1/state + 4: ACTIVE + + where driverX is mthca0, ipath5, ehca3, etc. + + To further test the InfiniBand software stack, use IPoIB (this + assumes you have two IB hosts named host1 and host2): + + host1> ifconfig ib0 a.b.c.x + host2> ifconfig ib0 a.b.c.y + host1> ping a.b.c.y + host2> ping a.b.c.x + + For other device types, follow the appropriate procedures. + + - Check NFS Setup + + For the NFS components enabled above (client and/or server), + test their functionality over standard Ethernet using TCP/IP or UDP/IP. + +NFS/RDMA Setup +~~~~~~~~~~~~~~ + + We recommend that you use two machines, one to act as the client and + one to act as the server. + + One time configuration: + + - On the server system, configure the /etc/exports file and + start the NFS/RDMA server. + + Exports entries with the following format have been tested: + + /vol0 10.97.103.47(rw,async) 192.168.0.47(rw,async,insecure,no_root_squash) + + Here the first IP address is the client's Ethernet address and the second + IP address is the clients IPoIB address. + + Each time a machine boots: + + - Load and configure the RDMA drivers + + For InfiniBand using a Mellanox adapter: + + > modprobe ib_mthca + > modprobe ib_ipoib + > ifconfig ib0 a.b.c.d + + NOTE: use unique addresses for the client and server + + - Start the NFS server + + If the NFS/RDMA server was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config), + load the RDMA transport module: + + > modprobe svcrdma + + Regardless of how the server was built (module or built-in), start the server: + + > /etc/init.d/nfs start + + or + + > service nfs start + + Instruct the server to listen on the RDMA transport: + + > echo rdma 2050 > /proc/fs/nfsd/portlist + + - On the client system + + If the NFS/RDMA client was built as a module (CONFIG_SUNRPC_XPRT_RDMA=m in kernel config), + load the RDMA client module: + + > modprobe xprtrdma.ko + + Regardless of how the client was built (module or built-in), issue the mount.nfs command: + + > /path/to/your/mount.nfs :/ /mnt -i -o rdma,port=2050 + + To verify that the mount is using RDMA, run "cat /proc/mounts" and check the + "proto" field for the given mount. + + Congratulations! You're using NFS/RDMA! -- cgit v1.2.3 From f12462c5224bf992f5ed4d37af4d42622f7d5934 Mon Sep 17 00:00:00 2001 From: Mirco Tischler Date: Mon, 4 Feb 2008 12:33:59 +0100 Subject: [ALSA] hda-codec - Add support of Zepto laptops Adds support for zepto laptops with alc268 intel_hda codec. Signed-off-by: Mirco Tischler Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 1 + sound/pci/hda/patch_realtek.c | 19 +++++++++++++++++++ 2 files changed, 20 insertions(+) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index e985cf5e0410..9a56b9b273cd 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -826,6 +826,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. toshiba Toshiba A205 acer Acer laptops dell Dell OEM laptops (Vostro 1200) + zepto Zepto laptops test for testing/debugging purpose, almost all controls can adjusted. Appearing only when compiled with $CONFIG_SND_DEBUG=y diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 33282f9c01c7..45e661e42c0b 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -107,6 +107,7 @@ enum { ALC268_TOSHIBA, ALC268_ACER, ALC268_DELL, + ALC268_ZEPTO, #ifdef CONFIG_SND_DEBUG ALC268_TEST, #endif @@ -10105,6 +10106,7 @@ static const char *alc268_models[ALC268_MODEL_LAST] = { [ALC268_TOSHIBA] = "toshiba", [ALC268_ACER] = "acer", [ALC268_DELL] = "dell", + [ALC268_ZEPTO] = "zepto", #ifdef CONFIG_SND_DEBUG [ALC268_TEST] = "test", #endif @@ -10122,6 +10124,7 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA), SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA), SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), + SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO), {} }; @@ -10182,6 +10185,22 @@ static struct alc_config_preset alc268_presets[] = { .init_hook = alc268_dell_init_hook, .input_mux = &alc268_capture_source, }, + [ALC268_ZEPTO] = { + .mixers = { alc268_base_mixer, alc268_capture_alt_mixer }, + .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, + alc268_toshiba_verbs }, + .num_dacs = ARRAY_SIZE(alc268_dac_nids), + .dac_nids = alc268_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), + .adc_nids = alc268_adc_nids_alt, + .hp_nid = 0x03, + .dig_out_nid = ALC268_DIGOUT_NID, + .num_channel_mode = ARRAY_SIZE(alc268_modes), + .channel_mode = alc268_modes, + .input_mux = &alc268_capture_source, + .unsol_event = alc268_toshiba_unsol_event, + .init_hook = alc268_toshiba_automute + }, #ifdef CONFIG_SND_DEBUG [ALC268_TEST] = { .mixers = { alc268_test_mixer, alc268_capture_mixer }, -- cgit v1.2.3 From c5059259688ab76f14f2f69a93e13575a36b614b Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 16 Feb 2008 09:43:56 +0100 Subject: [ALSA] hda-codec - Add support of AD1883/1884A/1984A/1984B Added the support of new AD codecs: AD1883, AD1884A, AD1984A and AD1984B. These are almost compatible except for additional digital pins, etc. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 4 + sound/pci/hda/patch_analog.c | 327 ++++++++++++++++++++++++ 2 files changed, 331 insertions(+) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 9a56b9b273cd..bfc6d486ad99 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -912,6 +912,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack 3-stack mode (default) 6stack 6-stack mode + AD1884A / AD1883 / AD1984A / AD1984B + desktop 3-stack desktop (default) + laptop laptop with HP jack sensing + AD1884 N/A diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 1f2102860fe8..b037fca1b44e 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3410,6 +3410,329 @@ static int patch_ad1984(struct hda_codec *codec) } +/* + * AD1883 / AD1884A / AD1984A / AD1984B + * + * port-B (0x14) - front mic-in + * port-E (0x1c) - rear mic-in + * port-F (0x16) - CD / ext out + * port-C (0x15) - rear line-in + * port-D (0x12) - rear line-out + * port-A (0x11) - front hp-out + * + * AD1984A = AD1884A + digital-mic + * AD1883 = equivalent with AD1984A + * AD1984B = AD1984A + extra SPDIF-out + * + * FIXME: + * We share the single DAC for both HP and line-outs (see AD1884/1984). + */ + +static hda_nid_t ad1884a_dac_nids[1] = { + 0x03, +}; + +#define ad1884a_adc_nids ad1884_adc_nids +#define ad1884a_capsrc_nids ad1884_capsrc_nids + +#define AD1884A_SPDIF_OUT 0x02 + +static struct hda_input_mux ad1884a_capture_source = { + .num_items = 5, + .items = { + { "Front Mic", 0x0 }, + { "Mic", 0x4 }, + { "Line", 0x1 }, + { "CD", 0x2 }, + { "Mix", 0x3 }, + }, +}; + +static struct snd_kcontrol_new ad1884a_base_mixers[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x11, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Front Playback Switch", 0x12, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x13, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x13, 1, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_MUTE("Front Mic Playback Switch", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_VOLUME("Line Playback Volume", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Line Playback Switch", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("CD Playback Volume", 0x20, 0x02, HDA_INPUT), + HDA_CODEC_MUTE("CD Playback Switch", 0x20, 0x02, HDA_INPUT), + HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), + HDA_CODEC_VOLUME("Front Mic Boost", 0x14, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Line Boost", 0x15, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x25, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* The multiple "Capture Source" controls confuse alsamixer + * So call somewhat different.. + */ + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 2, + .info = ad198x_mux_enum_info, + .get = ad198x_mux_enum_get, + .put = ad198x_mux_enum_put, + }, + /* SPDIF controls */ + HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Source", + /* identical with ad1983 */ + .info = ad1983_spdif_route_info, + .get = ad1983_spdif_route_get, + .put = ad1983_spdif_route_put, + }, + { } /* end */ +}; + +/* + * initialization verbs + */ +static struct hda_verb ad1884a_init_verbs[] = { + /* DACs; unmute as default */ + {0x03, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ + {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x27}, /* 0dB */ + /* Port-A (HP) mixer - route only from analog mixer */ + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* Port-A pin */ + {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Port-D (Line-out) mixer - route only from analog mixer */ + {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* Port-D pin */ + {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Mono-out mixer - route only from analog mixer */ + {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x1e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* Mono-out pin */ + {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Port-B (front mic) pin */ + {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Port-C (rear line-in) pin */ + {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Port-E (rear mic) pin */ + {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80}, + {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x25, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO}, /* no boost */ + /* Port-F (CD) pin */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* Analog mixer; mute as default */ + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)}, /* aux */ + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, + /* Analog Mix output amp */ + {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* capture sources */ + {0x0c, AC_VERB_SET_CONNECT_SEL, 0x0}, + {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + {0x0d, AC_VERB_SET_CONNECT_SEL, 0x0}, + {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* SPDIF output amp */ + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ + { } /* end */ +}; + +#ifdef CONFIG_SND_HDA_POWER_SAVE +static struct hda_amp_list ad1884a_loopbacks[] = { + { 0x20, HDA_INPUT, 0 }, /* Front Mic */ + { 0x20, HDA_INPUT, 1 }, /* Mic */ + { 0x20, HDA_INPUT, 2 }, /* CD */ + { 0x20, HDA_INPUT, 4 }, /* Docking */ + { } /* end */ +}; +#endif + +/* + * Laptop model + * + * Port A: Headphone jack + * Port B: MIC jack + * Port C: Internal MIC + * Port D: Dock Line Out (if enabled) + * Port E: Dock Line In (if enabled) + * Port F: Internal speakers + */ + +static struct hda_input_mux ad1884a_laptop_capture_source = { + .num_items = 4, + .items = { + { "Mic", 0x0 }, /* port-B */ + { "Internal Mic", 0x1 }, /* port-C */ + { "Dock Mic", 0x4 }, /* port-E */ + { "Mix", 0x3 }, + }, +}; + +static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Dock Playback Switch", 0x12, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x20, 0x04, HDA_INPUT), + HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x20, 0x04, HDA_INPUT), + HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Internal Mic Boost", 0x15, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Dock Mic Boost", 0x25, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x0d, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x0d, 0x0, HDA_OUTPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + /* The multiple "Capture Source" controls confuse alsamixer + * So call somewhat different.. + */ + /* .name = "Capture Source", */ + .name = "Input Source", + .count = 2, + .info = ad198x_mux_enum_info, + .get = ad198x_mux_enum_get, + .put = ad198x_mux_enum_put, + }, + { } /* end */ +}; + +/* mute internal speaker if HP is plugged */ +static void ad1884a_hp_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x11, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0, + HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); + snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_EAPD_BTLENABLE, + present ? 0x00 : 0x02); +} + +#define AD1884A_HP_EVENT 0x37 + +/* unsolicited event for HP jack sensing */ +static void ad1884a_hp_unsol_event(struct hda_codec *codec, unsigned int res) +{ + if ((res >> 26) != AD1884A_HP_EVENT) + return; + ad1884a_hp_automute(codec); +} + +/* initialize jack-sensing, too */ +static int ad1884a_hp_init(struct hda_codec *codec) +{ + ad198x_init(codec); + ad1884a_hp_automute(codec); + return 0; +} + +/* additional verbs for laptop model */ +static struct hda_verb ad1884a_laptop_verbs[] = { + /* Port-A (HP) pin - always unmuted */ + {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* Port-F (int speaker) mixer - route only from analog mixer */ + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, + {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)}, + /* Port-F pin */ + {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, + {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, + /* analog mix */ + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + /* unsolicited event for pin-sense */ + {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, + { } /* end */ +}; + +/* + */ + +enum { + AD1884A_DESKTOP, + AD1884A_LAPTOP, + AD1884A_MODELS +}; + +static const char *ad1884a_models[AD1884A_MODELS] = { + [AD1884A_DESKTOP] = "desktop", + [AD1884A_LAPTOP] = "laptop", +}; + +static int patch_ad1884a(struct hda_codec *codec) +{ + struct ad198x_spec *spec; + int board_config; + + spec = kzalloc(sizeof(*spec), GFP_KERNEL); + if (spec == NULL) + return -ENOMEM; + + mutex_init(&spec->amp_mutex); + codec->spec = spec; + + spec->multiout.max_channels = 2; + spec->multiout.num_dacs = ARRAY_SIZE(ad1884a_dac_nids); + spec->multiout.dac_nids = ad1884a_dac_nids; + spec->multiout.dig_out_nid = AD1884A_SPDIF_OUT; + spec->num_adc_nids = ARRAY_SIZE(ad1884a_adc_nids); + spec->adc_nids = ad1884a_adc_nids; + spec->capsrc_nids = ad1884a_capsrc_nids; + spec->input_mux = &ad1884a_capture_source; + spec->num_mixers = 1; + spec->mixers[0] = ad1884a_base_mixers; + spec->num_init_verbs = 1; + spec->init_verbs[0] = ad1884a_init_verbs; + spec->spdif_route = 0; +#ifdef CONFIG_SND_HDA_POWER_SAVE + spec->loopback.amplist = ad1884a_loopbacks; +#endif + codec->patch_ops = ad198x_patch_ops; + + /* override some parameters */ + board_config = snd_hda_check_board_config(codec, AD1884A_MODELS, + ad1884a_models, NULL); + switch (board_config) { + case AD1884A_LAPTOP: + spec->mixers[0] = ad1884a_laptop_mixers; + spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; + spec->multiout.dig_out_nid = 0; + spec->input_mux = &ad1884a_laptop_capture_source; + codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; + codec->patch_ops.init = ad1884a_hp_init; + break; + } + + return 0; +} + + /* * AD1882 * @@ -3709,8 +4032,12 @@ static int patch_ad1882(struct hda_codec *codec) * patch entries */ struct hda_codec_preset snd_hda_preset_analog[] = { + { .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a }, { .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 }, + { .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a }, { .id = 0x11d41884, .name = "AD1884", .patch = patch_ad1884 }, + { .id = 0x11d4194a, .name = "AD1984A", .patch = patch_ad1884a }, + { .id = 0x11d4194b, .name = "AD1984B", .patch = patch_ad1884a }, { .id = 0x11d41981, .name = "AD1981", .patch = patch_ad1981 }, { .id = 0x11d41983, .name = "AD1983", .patch = patch_ad1983 }, { .id = 0x11d41984, .name = "AD1984", .patch = patch_ad1984 }, -- cgit v1.2.3 From b40b04ad380ad641e5740486e4b9a56fd32b64cc Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Sat, 16 Feb 2008 09:44:56 +0100 Subject: [ALSA] hda-codec - Add model=mobile for AD1884A & co Added the new model mobile for AD1884A and compatible codecs. It's a reduced version of model=laptop. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 1 + sound/pci/hda/patch_analog.c | 48 ++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index bfc6d486ad99..2cfb8b469c53 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -915,6 +915,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. AD1884A / AD1883 / AD1984A / AD1984B desktop 3-stack desktop (default) laptop laptop with HP jack sensing + mobile mobile devices with HP jack sensing AD1884 N/A diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index b037fca1b44e..3f3905cc4e01 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3623,6 +3623,36 @@ static struct snd_kcontrol_new ad1884a_laptop_mixers[] = { { } /* end */ }; +static struct hda_input_mux ad1884a_mobile_capture_source = { + .num_items = 2, + .items = { + { "Mic", 0x1 }, /* port-C */ + { "Mix", 0x3 }, + }, +}; + +static struct snd_kcontrol_new ad1884a_mobile_mixers[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x01, HDA_INPUT), + HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x15, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = ad198x_mux_enum_info, + .get = ad198x_mux_enum_get, + .put = ad198x_mux_enum_put, + }, + { } /* end */ +}; + /* mute internal speaker if HP is plugged */ static void ad1884a_hp_automute(struct hda_codec *codec) { @@ -3677,12 +3707,19 @@ static struct hda_verb ad1884a_laptop_verbs[] = { enum { AD1884A_DESKTOP, AD1884A_LAPTOP, + AD1884A_MOBILE, AD1884A_MODELS }; static const char *ad1884a_models[AD1884A_MODELS] = { [AD1884A_DESKTOP] = "desktop", [AD1884A_LAPTOP] = "laptop", + [AD1884A_MOBILE] = "mobile", +}; + +static struct snd_pci_quirk ad1884a_cfg_tbl[] = { + SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), + {} }; static int patch_ad1884a(struct hda_codec *codec) @@ -3717,7 +3754,8 @@ static int patch_ad1884a(struct hda_codec *codec) /* override some parameters */ board_config = snd_hda_check_board_config(codec, AD1884A_MODELS, - ad1884a_models, NULL); + ad1884a_models, + ad1884a_cfg_tbl); switch (board_config) { case AD1884A_LAPTOP: spec->mixers[0] = ad1884a_laptop_mixers; @@ -3727,6 +3765,14 @@ static int patch_ad1884a(struct hda_codec *codec) codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; codec->patch_ops.init = ad1884a_hp_init; break; + case AD1884A_MOBILE: + spec->mixers[0] = ad1884a_mobile_mixers; + spec->init_verbs[spec->num_init_verbs++] = ad1884a_laptop_verbs; + spec->multiout.dig_out_nid = 0; + spec->input_mux = &ad1884a_mobile_capture_source; + codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; + codec->patch_ops.init = ad1884a_hp_init; + break; } return 0; -- cgit v1.2.3 From 9e235323db4689e8b7e123252b998a4904806c38 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 20 Feb 2008 12:13:29 +0100 Subject: [ALSA] Add description of aw2 driver Added a brief description of aw2 driver to ALSA-Configuration.txt. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 2cfb8b469c53..8a645a4555f2 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -284,6 +284,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. control correctly. If you have problems regarding this, try another ALSA compliant mixer (alsamixer works). + Module snd-aw2 + -------------- + + Module for Audiowerk2 sound card + + This module supports multiple cards. + Module snd-azt2320 ------------------ -- cgit v1.2.3 From 88d18ea2c2b40496b56efcb354e9eae1f09ef126 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 21 Feb 2008 14:11:09 +0100 Subject: [ALSA] hda-codec - Add missing descriptions for STAC codec models Added the missing descriptions for STAC codec models. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 8a645a4555f2..999b7048162a 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1030,6 +1030,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack D965 3stack 5stack D965 5stack + SPDIF dell-3stack Dell Dimension E520 + dell-bios Fixes with Dell BIOS setup + + STAC92HD71B* + ref Reference board + dell-m4-1 Dell desktops + dell-m4-2 Dell desktops + + STAC92HD73* + ref Reference board + dell-m6 Dell desktops STAC9872 vaio Setup for VAIO FE550G/SZ110 -- cgit v1.2.3 From d08cd58db9f4078bb9237fc6ff7104ed50d7804b Mon Sep 17 00:00:00 2001 From: Stas Sergeev Date: Thu, 6 Mar 2008 11:01:44 +0100 Subject: [ALSA] pcsp: add description update ALSA-Configuration.txt Signed-off-by: Stas Sergeev Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 999b7048162a..80a0629f4917 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -1613,6 +1613,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. Power management is _not_ supported. + Module snd-pcsp + ----------------- + + Module for internal PC-Speaker. + + nforce_wa - enable NForce chipset workaround. Expect bad sound. + + This module supports system beeps, some kind of PCM playback and + even a few mixer controls. + Module snd-pcxhr ---------------- -- cgit v1.2.3 From 117f257d7a9599ff9cb5ab7a6a10201c6294b5f1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Mar 2008 09:53:23 +0100 Subject: [ALSA] hda-codec - Fix spekaer output of Panasonic CF-74 Add a new model "panasonic" for Panasonic CF-74 with STAC9200 codec to fix the speaker output. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 1 + sound/pci/hda/patch_sigmatel.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 80a0629f4917..b02404395e52 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -992,6 +992,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. dell-m26 Dell Inspiron 1501 dell-m27 Dell Inspiron E1705/9400 gateway Gateway laptops with EAPD control + panasonic Panasonic CF-74 STAC9205/9254 ref Reference board diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index b8e69a1b93f0..a39fbd89a985 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c @@ -52,6 +52,7 @@ enum { STAC_9200_DELL_M26, STAC_9200_DELL_M27, STAC_9200_GATEWAY, + STAC_9200_PANASONIC, STAC_9200_MODELS }; @@ -1121,6 +1122,7 @@ static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = { [STAC_9200_DELL_M25] = dell9200_m25_pin_configs, [STAC_9200_DELL_M26] = dell9200_m26_pin_configs, [STAC_9200_DELL_M27] = dell9200_m27_pin_configs, + [STAC_9200_PANASONIC] = ref9200_pin_configs, }; static const char *stac9200_models[STAC_9200_MODELS] = { @@ -1137,6 +1139,7 @@ static const char *stac9200_models[STAC_9200_MODELS] = { [STAC_9200_DELL_M26] = "dell-m26", [STAC_9200_DELL_M27] = "dell-m27", [STAC_9200_GATEWAY] = "gateway", + [STAC_9200_PANASONIC] = "panasonic", }; static struct snd_pci_quirk stac9200_cfg_tbl[] = { @@ -1203,7 +1206,7 @@ static struct snd_pci_quirk stac9200_cfg_tbl[] = { SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01f6, "unknown Dell", STAC_9200_DELL_M26), /* Panasonic */ - SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_REF), + SND_PCI_QUIRK(0x10f7, 0x8338, "Panasonic CF-74", STAC_9200_PANASONIC), /* Gateway machines needs EAPD to be set on resume */ SND_PCI_QUIRK(0x107b, 0x0205, "Gateway S-7110M", STAC_9200_GATEWAY), SND_PCI_QUIRK(0x107b, 0x0317, "Gateway MT3423, MX341*", @@ -3302,6 +3305,11 @@ static int patch_stac9200(struct hda_codec *codec) spec->init = stac9200_core_init; spec->mixer = stac9200_mixer; + if (spec->board_config == STAC_9200_PANASONIC) { + spec->gpio_mask = spec->gpio_dir = 0x09; + spec->gpio_data = 0x00; + } + err = stac9200_parse_auto_config(codec); if (err < 0) { stac92xx_free(codec); -- cgit v1.2.3 From f081374b607f2656ca79a94d96d99cd5a2f60b68 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 18 Mar 2008 12:13:03 +0100 Subject: [ALSA] hda-codec - Support of Lenovo Thinkpad X300 Added the model thinkpad for Lenovo Thinkpad X300 with AD1984A codec. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 1 + sound/pci/hda/patch_analog.c | 94 +++++++++++++++++++++++++ 2 files changed, 95 insertions(+) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index b02404395e52..42dd8f5855da 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -923,6 +923,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. desktop 3-stack desktop (default) laptop laptop with HP jack sensing mobile mobile devices with HP jack sensing + thinkpad Lenovo Thinkpad X300 AD1884 N/A diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 220784bb76a7..2befeebd909e 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -3701,6 +3701,88 @@ static struct hda_verb ad1884a_laptop_verbs[] = { { } /* end */ }; +/* + * Thinkpad X300 + * 0x11 - HP + * 0x12 - speaker + * 0x14 - mic-in + * 0x17 - built-in mic + */ + +static struct hda_verb ad1984a_thinkpad_verbs[] = { + /* HP unmute */ + {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, + /* analog mix */ + {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, + /* turn on EAPD */ + {0x12, AC_VERB_SET_EAPD_BTLENABLE, 0x02}, + /* unsolicited event for pin-sense */ + {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | AD1884A_HP_EVENT}, + /* internal mic - dmic */ + {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, + { } /* end */ +}; + +static struct snd_kcontrol_new ad1984a_thinkpad_mixers[] = { + HDA_CODEC_VOLUME("Master Playback Volume", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Master Playback Switch", 0x21, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("PCM Playback Volume", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_MUTE("PCM Playback Switch", 0x20, 0x5, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Playback Volume", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_MUTE("Mic Playback Switch", 0x20, 0x00, HDA_INPUT), + HDA_CODEC_VOLUME("Beep Playback Volume", 0x20, 0x03, HDA_INPUT), + HDA_CODEC_MUTE("Beep Playback Switch", 0x20, 0x03, HDA_INPUT), + HDA_CODEC_VOLUME("Mic Boost", 0x14, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Internal Mic Boost", 0x17, 0x0, HDA_INPUT), + HDA_CODEC_VOLUME("Capture Volume", 0x0c, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Capture Switch", 0x0c, 0x0, HDA_OUTPUT), + { + .iface = SNDRV_CTL_ELEM_IFACE_MIXER, + .name = "Capture Source", + .info = ad198x_mux_enum_info, + .get = ad198x_mux_enum_get, + .put = ad198x_mux_enum_put, + }, + { } /* end */ +}; + +static struct hda_input_mux ad1984a_thinkpad_capture_source = { + .num_items = 3, + .items = { + { "Mic", 0x0 }, + { "Internal Mic", 0x5 }, + { "Mix", 0x3 }, + }, +}; + +/* mute internal speaker if HP is plugged */ +static void ad1984a_thinkpad_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x11, 0, AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + snd_hda_codec_amp_stereo(codec, 0x12, HDA_OUTPUT, 0, + HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); +} + +/* unsolicited event for HP jack sensing */ +static void ad1984a_thinkpad_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + if ((res >> 26) != AD1884A_HP_EVENT) + return; + ad1984a_thinkpad_automute(codec); +} + +/* initialize jack-sensing, too */ +static int ad1984a_thinkpad_init(struct hda_codec *codec) +{ + ad198x_init(codec); + ad1984a_thinkpad_automute(codec); + return 0; +} + /* */ @@ -3708,6 +3790,7 @@ enum { AD1884A_DESKTOP, AD1884A_LAPTOP, AD1884A_MOBILE, + AD1884A_THINKPAD, AD1884A_MODELS }; @@ -3715,10 +3798,12 @@ static const char *ad1884a_models[AD1884A_MODELS] = { [AD1884A_DESKTOP] = "desktop", [AD1884A_LAPTOP] = "laptop", [AD1884A_MOBILE] = "mobile", + [AD1884A_THINKPAD] = "thinkpad", }; static struct snd_pci_quirk ad1884a_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x3030, "HP", AD1884A_MOBILE), + SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X300", AD1884A_THINKPAD), {} }; @@ -3773,6 +3858,15 @@ static int patch_ad1884a(struct hda_codec *codec) codec->patch_ops.unsol_event = ad1884a_hp_unsol_event; codec->patch_ops.init = ad1884a_hp_init; break; + case AD1884A_THINKPAD: + spec->mixers[0] = ad1984a_thinkpad_mixers; + spec->init_verbs[spec->num_init_verbs++] = + ad1984a_thinkpad_verbs; + spec->multiout.dig_out_nid = 0; + spec->input_mux = &ad1984a_thinkpad_capture_source; + codec->patch_ops.unsol_event = ad1984a_thinkpad_unsol_event; + codec->patch_ops.init = ad1984a_thinkpad_init; + break; } return 0; -- cgit v1.2.3 From 5d85f8d02af56da5e3b76805da00a0f7f7427255 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Thu, 20 Mar 2008 12:13:46 +0100 Subject: [ALSA] hda-codec - Remove now uneeded 6stack-hp model from ALC883 After DAC assignment fix in ALC883, the 6stack-hp model is now the same as 6stack-dig. So just remove 6stack-hp model and replace its use with 6stack-dig. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 1 - sound/pci/hda/patch_realtek.c | 55 +------------------------ 2 files changed, 1 insertion(+), 55 deletions(-) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 42dd8f5855da..0fb62f65938a 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -879,7 +879,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. lenovo-nb0763 Lenovo NB0763 lenovo-ms7195-dig Lenovo MS7195 haier-w66 Haier W66 - 6stack-hp HP machines with 6stack (Nettle boards) 3stack-hp HP machines with 3stack (Lucknow, Samba boards) 6stack-dell Dell machines with 6stack (Inspiron 530) mitac Mitac 8252D diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 8b819072af3a..15b4704539fd 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -198,7 +198,6 @@ enum { ALC883_LENOVO_NB0763, ALC888_LENOVO_MS7195_DIG, ALC883_HAIER_W66, - ALC888_6ST_HP, ALC888_3ST_HP, ALC888_6ST_DELL, ALC883_MITAC, @@ -6956,46 +6955,6 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = { { } /* end */ }; -static struct snd_kcontrol_new alc888_6st_hp_mixer[] = { - HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT), - HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT), - HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT), - HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT), - HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT), - HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT), - HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT), - HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT), - HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT), - HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), - HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), - HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT), - HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT), - HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT), - { - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, - /* .name = "Capture Source", */ - .name = "Input Source", - .count = 2, - .info = alc883_mux_enum_info, - .get = alc883_mux_enum_get, - .put = alc883_mux_enum_put, - }, - { } /* end */ -}; - static struct snd_kcontrol_new alc888_3st_hp_mixer[] = { HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT), @@ -7721,7 +7680,6 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { [ALC883_LENOVO_NB0763] = "lenovo-nb0763", [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig", [ALC883_HAIER_W66] = "haier-w66", - [ALC888_6ST_HP] = "6stack-hp", [ALC888_3ST_HP] = "3stack-hp", [ALC888_6ST_DELL] = "6stack-dell", [ALC883_MITAC] = "mitac", @@ -7740,7 +7698,7 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG), SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP), SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP), - SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC888_6ST_HP), + SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG), SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC), @@ -7973,17 +7931,6 @@ static struct alc_config_preset alc883_presets[] = { .unsol_event = alc883_haier_w66_unsol_event, .init_hook = alc883_haier_w66_automute, }, - [ALC888_6ST_HP] = { - .mixers = { alc888_6st_hp_mixer, alc883_chmode_mixer }, - .init_verbs = { alc883_init_verbs }, - .num_dacs = ARRAY_SIZE(alc883_dac_nids), - .dac_nids = alc883_dac_nids, - .dig_out_nid = ALC883_DIGOUT_NID, - .dig_in_nid = ALC883_DIGIN_NID, - .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes), - .channel_mode = alc883_sixstack_modes, - .input_mux = &alc883_capture_source, - }, [ALC888_3ST_HP] = { .mixers = { alc888_3st_hp_mixer, alc883_chmode_mixer }, .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs }, -- cgit v1.2.3 From cd97f47df377d2371940b69fa4c8b4d99a980580 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Thu, 20 Mar 2008 12:30:36 +0100 Subject: [ALSA] hda-codec - Add missing models in ALSA-Configuration.txt Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 0fb62f65938a..3eea0675ebb0 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -825,6 +825,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. hippo_1 Hippo (Benq) with jack detection sony-assamd Sony ASSAMD ultra Samsung Q1 Ultra Vista model + lenovo-3000 Lenovo 3000 y410 basic fixed pin assignment w/o SPDIF auto auto-config reading BIOS (default) @@ -839,6 +840,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. $CONFIG_SND_DEBUG=y auto auto-config reading BIOS (default) + ALC269 + basic Basic preset + ALC662 3stack-dig 3-stack (2-channel) with SPDIF 3stack-6ch 3-stack (6-channel) @@ -882,6 +886,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack-hp HP machines with 3stack (Lucknow, Samba boards) 6stack-dell Dell machines with 6stack (Inspiron 530) mitac Mitac 8252D + clevo-m720r Clevo laptop M720R + fujitsu-pi2515 Fujitsu AMILO Pi2515 auto auto-config reading BIOS (default) ALC861/660 -- cgit v1.2.3 From 0c4cc4430f40089bb85557e309038faa458247f1 Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Sat, 22 Mar 2008 10:26:05 +0100 Subject: [ALSA] hda-codec - Support mic automute for Clevo M720R/SR Add support for mic automute in clevo-m720r ALC883 model, and rename it to more generic clevo-m720. Also change model entry in ALSA-Configuration.txt accordingly. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 2 +- sound/pci/hda/patch_realtek.c | 53 ++++++++++++++++++------- 2 files changed, 39 insertions(+), 16 deletions(-) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 3eea0675ebb0..08256fcb2743 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -886,7 +886,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. 3stack-hp HP machines with 3stack (Lucknow, Samba boards) 6stack-dell Dell machines with 6stack (Inspiron 530) mitac Mitac 8252D - clevo-m720r Clevo laptop M720R + clevo-m720 Clevo M720 laptop series fujitsu-pi2515 Fujitsu AMILO Pi2515 auto auto-config reading BIOS (default) diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index e137882d9459..e5d97c12381d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -201,7 +201,7 @@ enum { ALC888_3ST_HP, ALC888_6ST_DELL, ALC883_MITAC, - ALC883_CLEVO_M720R, + ALC883_CLEVO_M720, ALC883_FUJITSU_PI2515, ALC883_AUTO, ALC883_MODEL_LAST, @@ -6661,7 +6661,7 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = { { } /* end */ }; -static struct snd_kcontrol_new alc883_clevo_m720r_mixer[] = { +static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = { HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT), HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT), HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT), @@ -7130,7 +7130,7 @@ static struct hda_verb alc883_mitac_verbs[] = { { } /* end */ }; -static struct hda_verb alc883_clevo_m720r_verbs[] = { +static struct hda_verb alc883_clevo_m720_verbs[] = { /* HP */ {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, @@ -7140,6 +7140,7 @@ static struct hda_verb alc883_clevo_m720r_verbs[] = { /* enable unsolicited event */ {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, { } /* end */ }; @@ -7330,7 +7331,7 @@ static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res) } /* toggle speaker-output according to the hp-jack state */ -static void alc883_clevo_m720r_automute(struct hda_codec *codec) +static void alc883_clevo_m720_hp_automute(struct hda_codec *codec) { unsigned int present; unsigned char bits; @@ -7342,11 +7343,33 @@ static void alc883_clevo_m720r_automute(struct hda_codec *codec) HDA_AMP_MUTE, bits); } -static void alc883_clevo_m720r_unsol_event(struct hda_codec *codec, +static void alc883_clevo_m720_mic_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x18, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, + HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0); +} + +static void alc883_clevo_m720_automute(struct hda_codec *codec) +{ + alc883_clevo_m720_hp_automute(codec); + alc883_clevo_m720_mic_automute(codec); +} + +static void alc883_clevo_m720_unsol_event(struct hda_codec *codec, unsigned int res) { - if ((res >> 26) == ALC880_HP_EVENT) - alc883_clevo_m720r_automute(codec); + switch (res >> 26) { + case ALC880_HP_EVENT: + alc883_clevo_m720_hp_automute(codec); + break; + case ALC880_MIC_EVENT: + alc883_clevo_m720_mic_automute(codec); + break; + } } /* toggle speaker-output according to the hp-jack state */ @@ -7605,7 +7628,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = { [ALC888_3ST_HP] = "3stack-hp", [ALC888_6ST_DELL] = "6stack-dell", [ALC883_MITAC] = "mitac", - [ALC883_CLEVO_M720R] = "clevo-m720r", + [ALC883_CLEVO_M720] = "clevo-m720", [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515", [ALC883_AUTO] = "auto", }; @@ -7649,8 +7672,8 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = { SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG), SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG), SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG), - SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720R), - SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720R), + SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720), + SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720), SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD), SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch), SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION), @@ -7794,17 +7817,17 @@ static struct alc_config_preset alc883_presets[] = { .channel_mode = alc883_3ST_2ch_modes, .input_mux = &alc883_capture_source, }, - [ALC883_CLEVO_M720R] = { - .mixers = { alc883_clevo_m720r_mixer }, - .init_verbs = { alc883_init_verbs, alc883_clevo_m720r_verbs }, + [ALC883_CLEVO_M720] = { + .mixers = { alc883_clevo_m720_mixer }, + .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs }, .num_dacs = ARRAY_SIZE(alc883_dac_nids), .dac_nids = alc883_dac_nids, .dig_out_nid = ALC883_DIGOUT_NID, .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes), .channel_mode = alc883_3ST_2ch_modes, .input_mux = &alc883_capture_source, - .unsol_event = alc883_clevo_m720r_unsol_event, - .init_hook = alc883_clevo_m720r_automute, + .unsol_event = alc883_clevo_m720_unsol_event, + .init_hook = alc883_clevo_m720_automute, }, [ALC883_LENOVO_101E_2ch] = { .mixers = { alc883_lenovo_101e_2ch_mixer}, -- cgit v1.2.3 From eb5a66216658a1c879ab05dcdc65ce7005c4780b Mon Sep 17 00:00:00 2001 From: Herton Ronaldo Krzesinski Date: Mon, 14 Apr 2008 13:46:28 +0200 Subject: [ALSA] hda-intel: Add Quanta IL1 ALC267 model This adds support for Quanta IL1 mini-notebook to alsa, defining a new model for it. It comes with an ALC267 codec chip. Some notes about this model: * In headphone automute, I use AC_VERB_SET_PIN_WIDGET_CONTROL instead of common amp mute, to avoid conflict with mixer switch (mixer and automute use the same nid). * The only connected capture sources in the hardware are the internal mic and external mic jack. So instead of using an input source selector like on other ALC268 models, the mic automute automatically switch between captures. Signed-off-by: Herton Ronaldo Krzesinski Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 3 +- sound/pci/hda/patch_realtek.c | 76 +++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 08256fcb2743..3413644dff1e 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -829,7 +829,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. basic fixed pin assignment w/o SPDIF auto auto-config reading BIOS (default) - ALC268 + ALC267/268 + quanta-il1 Quanta IL1 mini-notebook 3stack 3-stack model toshiba Toshiba A205 acer Acer laptops diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 830d6626e10e..181db2177a1d 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -105,6 +105,7 @@ enum { /* ALC268 models */ enum { + ALC267_QUANTA_IL1, ALC268_3ST, ALC268_TOSHIBA, ALC268_ACER, @@ -9902,6 +9903,64 @@ static void alc268_dell_unsol_event(struct hda_codec *codec, #define alc268_dell_init_hook alc268_dell_automute +static struct snd_kcontrol_new alc267_quanta_il1_mixer[] = { + HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT), + HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT), + HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT), + HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT), + HDA_CODEC_VOLUME("Ext Mic Boost", 0x18, 0, HDA_INPUT), + HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT), + { } +}; + +static struct hda_verb alc267_quanta_il1_verbs[] = { + {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, + {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, + { } +}; + +static void alc267_quanta_il1_hp_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_PIN_SENSE, 0) + & AC_PINSENSE_PRESENCE; + snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, + present ? 0 : PIN_OUT); +} + +static void alc267_quanta_il1_mic_automute(struct hda_codec *codec) +{ + unsigned int present; + + present = snd_hda_codec_read(codec, 0x18, 0, + AC_VERB_GET_PIN_SENSE, 0) & 0x80000000; + snd_hda_codec_write(codec, 0x23, 0, + AC_VERB_SET_CONNECT_SEL, + present ? 0x00 : 0x01); +} + +static void alc267_quanta_il1_automute(struct hda_codec *codec) +{ + alc267_quanta_il1_hp_automute(codec); + alc267_quanta_il1_mic_automute(codec); +} + +static void alc267_quanta_il1_unsol_event(struct hda_codec *codec, + unsigned int res) +{ + switch (res >> 26) { + case ALC880_HP_EVENT: + alc267_quanta_il1_hp_automute(codec); + break; + case ALC880_MIC_EVENT: + alc267_quanta_il1_mic_automute(codec); + break; + } +} + /* * generic initialization of ADC, input mixers and output mixers */ @@ -10324,6 +10383,7 @@ static void alc268_auto_init(struct hda_codec *codec) * configuration and preset */ static const char *alc268_models[ALC268_MODEL_LAST] = { + [ALC267_QUANTA_IL1] = "quanta-il1", [ALC268_3ST] = "3stack", [ALC268_TOSHIBA] = "toshiba", [ALC268_ACER] = "acer", @@ -10346,11 +10406,27 @@ static struct snd_pci_quirk alc268_cfg_tbl[] = { SND_PCI_QUIRK(0x1179, 0xff10, "TOSHIBA A205", ALC268_TOSHIBA), SND_PCI_QUIRK(0x1179, 0xff50, "TOSHIBA A305", ALC268_TOSHIBA), SND_PCI_QUIRK(0x152d, 0x0763, "Diverse (CPR2000)", ALC268_ACER), + SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1), SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO), {} }; static struct alc_config_preset alc268_presets[] = { + [ALC267_QUANTA_IL1] = { + .mixers = { alc267_quanta_il1_mixer }, + .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs, + alc267_quanta_il1_verbs }, + .num_dacs = ARRAY_SIZE(alc268_dac_nids), + .dac_nids = alc268_dac_nids, + .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt), + .adc_nids = alc268_adc_nids_alt, + .hp_nid = 0x03, + .num_channel_mode = ARRAY_SIZE(alc268_modes), + .channel_mode = alc268_modes, + .input_mux = &alc268_capture_source, + .unsol_event = alc267_quanta_il1_unsol_event, + .init_hook = alc267_quanta_il1_automute, + }, [ALC268_3ST] = { .mixers = { alc268_base_mixer, alc268_capture_alt_mixer, alc268_beep_mixer }, -- cgit v1.2.3 From 3adb8abc70aaf5c071f27576069c8b01783cca83 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 15 Apr 2008 18:46:42 +0200 Subject: [ALSA] hda - Add support of AD1989A/AD1989B Added the support of AD1989A and AD1989B codecs. These codecs can have multiple SPDIF devices, but currently we handle only one SPDIF. If any real devices with two SPDIF interfaces (likely one for SPDIF and one for HDMI), we'll fix this rightly. Otherwise, these codecs are pretty similar with AD1988. Signed-off-by: Takashi Iwai --- Documentation/sound/alsa/ALSA-Configuration.txt | 2 +- sound/pci/hda/patch_analog.c | 28 ++++++++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt index 3413644dff1e..fd4c32a031c9 100644 --- a/Documentation/sound/alsa/ALSA-Configuration.txt +++ b/Documentation/sound/alsa/ALSA-Configuration.txt @@ -956,7 +956,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed. laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100) ultra 2-channel with EAPD (Samsung Ultra tablet PC) - AD1988 + AD1988/AD1988B/AD1989A/AD1989B 6stack 6-jack 6stack-dig ditto with SPDIF 3stack 3-jack diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 2befeebd909e..f486eb16a386 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c @@ -2142,6 +2142,10 @@ static struct snd_kcontrol_new ad1988_spdif_in_mixers[] = { { } /* end */ }; +static struct snd_kcontrol_new ad1989_spdif_out_mixers[] = { + HDA_CODEC_VOLUME("IEC958 Playback Volume", 0x1b, 0x0, HDA_OUTPUT), + { } /* end */ +}; /* * initialization verbs @@ -2242,6 +2246,13 @@ static struct hda_verb ad1988_spdif_init_verbs[] = { { } }; +/* AD1989 has no ADC -> SPDIF route */ +static struct hda_verb ad1989_spdif_init_verbs[] = { + /* SPDIF out pin */ + {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE | 0x27}, /* 0dB */ + { } +}; + /* * verbs for 3stack (+dig) */ @@ -2949,10 +2960,19 @@ static int patch_ad1988(struct hda_codec *codec) spec->mixers[spec->num_mixers++] = ad1988_capture_mixers; spec->init_verbs[spec->num_init_verbs++] = ad1988_capture_init_verbs; if (spec->multiout.dig_out_nid) { - spec->mixers[spec->num_mixers++] = ad1988_spdif_out_mixers; - spec->init_verbs[spec->num_init_verbs++] = ad1988_spdif_init_verbs; + if (codec->vendor_id >= 0x11d4989a) { + spec->mixers[spec->num_mixers++] = + ad1989_spdif_out_mixers; + spec->init_verbs[spec->num_init_verbs++] = + ad1989_spdif_init_verbs; + } else { + spec->mixers[spec->num_mixers++] = + ad1988_spdif_out_mixers; + spec->init_verbs[spec->num_init_verbs++] = + ad1988_spdif_init_verbs; + } } - if (spec->dig_in_nid) + if (spec->dig_in_nid && codec->vendor_id < 0x11d4989a) spec->mixers[spec->num_mixers++] = ad1988_spdif_in_mixers; codec->patch_ops = ad198x_patch_ops; @@ -4184,5 +4204,7 @@ struct hda_codec_preset snd_hda_preset_analog[] = { { .id = 0x11d41986, .name = "AD1986A", .patch = patch_ad1986a }, { .id = 0x11d41988, .name = "AD1988", .patch = patch_ad1988 }, { .id = 0x11d4198b, .name = "AD1988B", .patch = patch_ad1988 }, + { .id = 0x11d4989a, .name = "AD1989A", .patch = patch_ad1988 }, + { .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 }, {} /* terminator */ }; -- cgit v1.2.3 From 6ab465a821756691009e58a51f1b4543cf1ae21a Mon Sep 17 00:00:00 2001 From: Hartmut Hackmann Date: Tue, 22 Apr 2008 14:42:11 -0300 Subject: V4L/DVB (7226): saa7134: add support for the NXP Snake DVB-S reference design Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 26 ++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 13 +++++++++++++ drivers/media/video/saa7134/saa7134.h | 3 ++- 4 files changed, 42 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 0424901ebc78..3ec78d4cfea3 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -131,3 +131,4 @@ 130 -> Beholder BeholdTV M6 / BeholdTV M6 Extra [5ace:6190,5ace:6193] 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 132 -> Genius TVGO AM11MCE +133 -> NXP Snake DVB-S reference design diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 6f5744286e8c..16cd319dc4e6 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -3992,6 +3992,24 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x6000, }, }, + [SAA7134_BOARD_PHILIPS_SNAKE] = { + .name = "NXP Snake DVB-S reference design", + .audio_clock = 0x00200000, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5283,6 +5301,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; case SAA7134_BOARD_PHILIPS_EUROPA: + if (dev->autodetected && (dev->eedata[0x41] == 0x1c)) { + /* Reconfigure board as Snake reference design */ + dev->board = SAA7134_BOARD_PHILIPS_SNAKE; + dev->tuner_type = saa7134_boards[dev->board].tuner_type; + printk(KERN_INFO "%s: Reconfigured board as %s\n", + dev->name, saa7134_boards[dev->board].name); + break; + } case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_ASUS_EUROPA2_HYBRID: /* The Philips EUROPA based hybrid boards have the tuner connected through diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 72fd9fed8a34..5d20ec06e48d 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -44,6 +44,7 @@ #include "tda827x.h" #include "isl6421.h" #include "isl6405.h" +#include "lnbp21.h" MODULE_AUTHOR("Gerd Knorr [SuSE Labs]"); MODULE_LICENSE("GPL"); @@ -1080,6 +1081,18 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: configure_tda827x_fe(dev, &twinhan_dtv_dvb_3056_config); break; + case SAA7134_BOARD_PHILIPS_SNAKE: + dev->dvb.frontend = dvb_attach(tda10086_attach, &flydvbs, + &dev->i2c_adap); + if (dev->dvb.frontend) { + if (dvb_attach(tda826x_attach, dev->dvb.frontend, 0x60, + &dev->i2c_adap, 0) == NULL) + wprintk("%s: No tda826x found!\n", __FUNCTION__); + if (dvb_attach(lnbp21_attach, dev->dvb.frontend, + &dev->i2c_adap, 0, 0) == NULL) + wprintk("%s: No lnbp21 found!\n", __FUNCTION__); + } + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index f940d0254798..4dc66f4b0e4a 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -253,7 +253,8 @@ struct saa7134_format { #define SAA7134_BOARD_BEHOLD_607_9FM 129 #define SAA7134_BOARD_BEHOLD_M6 130 #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 -#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 +#define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 +#define SAA7134_BOARD_PHILIPS_SNAKE 133 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 7b5b3f1765c9773ec9b10c3e5299ac001211a80d Mon Sep 17 00:00:00 2001 From: Hermann Pitton Date: Tue, 22 Apr 2008 14:42:12 -0300 Subject: V4L/DVB (7229): saa7134: add support for the Creatix CTX953_V.1.4.3 Hybrid Signed-off-by: Hermann Pitton Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 31 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 3 +++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 36 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 3ec78d4cfea3..bae05ff515df 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -132,3 +132,4 @@ 131 -> Twinhan Hybrid DTV-DVB 3056 PCI [1822:0022] 132 -> Genius TVGO AM11MCE 133 -> NXP Snake DVB-S reference design +134 -> Medion/Creatix CTX953 Hybrid [16be:0010] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 16cd319dc4e6..a827af4546d0 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4010,6 +4010,30 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, } }, }, + [SAA7134_BOARD_CREATIX_CTX953] = { + .name = "Medion/Creatix CTX953 Hybrid", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 0, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 0, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4960,6 +4984,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x1822, /*Twinhan Technology Co. Ltd*/ .subdevice = 0x0022, .driver_data = SAA7134_BOARD_TWINHAN_DTV_DVB_3056, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x16be, + .subdevice = 0x0010, /* Medion version CTX953_V.1.4.3 */ + .driver_data = SAA7134_BOARD_CREATIX_CTX953, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, @@ -5359,6 +5389,7 @@ int saa7134_board_init2(struct saa7134_dev *dev) case SAA7134_BOARD_MEDION_MD8800_QUADRO: case SAA7134_BOARD_AVERMEDIA_SUPER_007: case SAA7134_BOARD_TWINHAN_DTV_DVB_3056: + case SAA7134_BOARD_CREATIX_CTX953: /* this is a hybrid board, initialize to analog mode * and configure firmware eeprom address */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 180d3193c971..683a67561a6e 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1136,6 +1136,9 @@ static int dvb_init(struct saa7134_dev *dev) wprintk("%s: No lnbp21 found!\n", __FUNCTION__); } break; + case SAA7134_BOARD_CREATIX_CTX953: + configure_tda827x_fe(dev, &md8800_dvbt_config); + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 2b7661f58a70..e483209b6854 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -255,6 +255,7 @@ struct saa7134_format { #define SAA7134_BOARD_TWINHAN_DTV_DVB_3056 131 #define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 #define SAA7134_BOARD_PHILIPS_SNAKE 133 +#define SAA7134_BOARD_CREATIX_CTX953 134 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 6a6179b6db401acde5798b4da0fdff32b126ee15 Mon Sep 17 00:00:00 2001 From: Russell Kliese Date: Tue, 22 Apr 2008 14:42:12 -0300 Subject: V4L/DVB (7230): saa7134: add support for the MSI TV@nywhere A/D v1.1 card Signed-off-by: Russell Kliese Signed-off-by: Hartmut Hackmann Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 1 + drivers/media/video/saa7134/saa7134-cards.c | 36 +++++++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-dvb.c | 3 +++ drivers/media/video/saa7134/saa7134.h | 1 + 4 files changed, 41 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index bae05ff515df..765a06b1f0f6 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -133,3 +133,4 @@ 132 -> Genius TVGO AM11MCE 133 -> NXP Snake DVB-S reference design 134 -> Medion/Creatix CTX953 Hybrid [16be:0010] +135 -> MSI TV@nywhere A/D v1.1 [1462:8625] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index a827af4546d0..f9c85b7cba1a 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4034,6 +4034,36 @@ struct saa7134_board saa7134_boards[] = { .amux = LINE1, } }, }, + [SAA7134_BOARD_MSI_TVANYWHERE_AD11] = { + .name = "MSI TV@nywhere A/D v1.1", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_PHILIPS_TDA8290, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .tuner_config = 2, + .mpeg = SAA7134_MPEG_DVB, + .gpiomask = 0x0200000, + .inputs = { { + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + .gpio = 0x0200000, + }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4990,6 +5020,12 @@ struct pci_device_id saa7134_pci_tbl[] = { .subvendor = 0x16be, .subdevice = 0x0010, /* Medion version CTX953_V.1.4.3 */ .driver_data = SAA7134_BOARD_CREATIX_CTX953, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1462, /* MSI */ + .subdevice = 0x8625, /* TV@nywhere A/D v1.1 */ + .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11, },{ /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index 683a67561a6e..b55df4877aff 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -1139,6 +1139,9 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_CREATIX_CTX953: configure_tda827x_fe(dev, &md8800_dvbt_config); break; + case SAA7134_BOARD_MSI_TVANYWHERE_AD11: + configure_tda827x_fe(dev, &philips_tiger_s_config); + break; default: wprintk("Huh? unknown DVB card?\n"); break; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index e483209b6854..d7e0781fe8a1 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -256,6 +256,7 @@ struct saa7134_format { #define SAA7134_BOARD_GENIUS_TVGO_A11MCE 132 #define SAA7134_BOARD_PHILIPS_SNAKE 133 #define SAA7134_BOARD_CREATIX_CTX953 134 +#define SAA7134_BOARD_MSI_TVANYWHERE_AD11 135 #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 -- cgit v1.2.3 From 5c00fac0bab95a378e60c1a67e3d3c5ac44df412 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 22 Apr 2008 14:45:14 -0300 Subject: V4L/DVB (7252): cx88: Add support for the Dvico PCI Nano ATSC is known to work. SVideo / Composite should work (I have no cable to test). Analog tuner support does not work. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 27 +++++++++++++ drivers/media/video/cx88/cx88-dvb.c | 69 +++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 98 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index bc5593bd9704..79c166a7f230 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -57,3 +57,4 @@ 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602] 57 -> ADS Tech Instant Video PCI [1421:0390] 58 -> Pinnacle PCTV HD 800i [11bd:0051] + 59 -> DVICO HDTV5 PCI Nano [18ac:d530] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 8c9a8adf52de..23b58bc9cf2b 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1401,6 +1401,29 @@ static const struct cx88_board cx88_boards[] = { }}, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = { + .name = "DVICO HDTV5 PCI Nano", + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x000027df, /* Unconfirmed */ + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000027df, /* Unconfirmed */ + .audioroute = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000027df, /* Unconfirmed */ + .audioroute = 1, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -1714,6 +1737,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x11bd, .subdevice = 0x0051, .card = CX88_BOARD_PINNACLE_PCTV_HD_800i, + }, { + .subvendor = 0x18ac, + .subdevice = 0xd530, + .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO, }, }; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index fa21666966e6..735376060df2 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -45,6 +45,8 @@ #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" +#include "tuner-xc2028.h" +#include "tuner-xc2028-types.h" MODULE_DESCRIPTION("driver for cx2388x based DVB cards"); MODULE_AUTHOR("Chris Pascoe "); @@ -357,6 +359,40 @@ static int geniatech_dvbs_set_voltage(struct dvb_frontend *fe, return 0; } +static int cx88_xc3028_callback(void *ptr, int command, int arg) +{ + struct cx88_core *core = ptr; + + switch (command) { + case XC2028_TUNER_RESET: + /* Send the tuner in then out of reset */ + dprintk(1, "%s: XC2028_TUNER_RESET %d\n", __FUNCTION__, arg); + + switch (core->boardnr) { + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + /* GPIO-4 xc3028 tuner */ + + cx_set(MO_GP0_IO, 0x00001000); + cx_clear(MO_GP0_IO, 0x00000010); + msleep(100); + cx_set(MO_GP0_IO, 0x00000010); + msleep(100); + break; + } + + break; + case XC2028_RESET_CLK: + dprintk(1, "%s: XC2028_RESET_CLK %d\n", __FUNCTION__, arg); + break; + default: + dprintk(1, "%s: unknown command %d, arg %d\n", __FUNCTION__, + command, arg); + return -EINVAL; + } + + return 0; +} + static struct cx24123_config geniatech_dvbs_config = { .demod_address = 0x55, .set_ts_params = cx24123_set_ts_param, @@ -383,6 +419,15 @@ static struct s5h1409_config pinnacle_pctv_hd_800i_config = { .mpeg_timing = S5H1409_MPEGTIMING_NONCONTINOUS_NONINVERTING_CLOCK, }; +static struct s5h1409_config dvico_hdtv5_pci_nano_config = { + .demod_address = 0x32 >> 1, + .output_mode = S5H1409_SERIAL_OUTPUT, + .gpio = S5H1409_GPIO_OFF, + .inversion = S5H1409_INVERSION_OFF, + .status_mode = S5H1409_DEMODLOCKING, + .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, +}; + static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .i2c_address = 0x64, .if_khz = 5380, @@ -658,6 +703,30 @@ static int dvb_register(struct cx8802_dev *dev) &pinnacle_pctv_hd_800i_tuner_config); } break; + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + dev->dvb.frontend = dvb_attach(s5h1409_attach, + &dvico_hdtv5_pci_nano_config, + &dev->core->i2c_adap); + if (dev->dvb.frontend != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->core->i2c_adap, + .i2c_addr = 0x61, + .video_dev = dev->core, + .callback = cx88_xc3028_callback, + }; + static struct xc2028_ctrl ctl = { + .fname = "xc3028-v27.fw", + .max_len = 64, + .scode_table = OREN538, + }; + + fe = dvb_attach(xc2028_attach, + dev->dvb.frontend, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctl); + } + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 37e6d2e4002f..8121bd07a88a 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -211,6 +211,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_HAUPPAUGE_HVR1300 56 #define CX88_BOARD_ADSTECH_PTV_390 57 #define CX88_BOARD_PINNACLE_PCTV_HD_800i 58 +#define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 8efd2e28265ca031072d8d94cdbdd53904ce9b2d Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:14 -0300 Subject: V4L/DVB (7254): cx88: fix FusionHDTV 5 PCI nano name and enable IR support load ir-kbd-i2c for IR remote control support on DViCO FusionHDTV 5 PCI nano Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 2 +- drivers/media/video/cx88/cx88-cards.c | 3 ++- drivers/media/video/cx88/cx88-video.c | 4 +++- 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 79c166a7f230..7d48e3dbd074 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -57,4 +57,4 @@ 56 -> Hauppauge WinTV-HVR1300 DVB-T/Hybrid MPEG Encoder [0070:9600,0070:9601,0070:9602] 57 -> ADS Tech Instant Video PCI [1421:0390] 58 -> Pinnacle PCTV HD 800i [11bd:0051] - 59 -> DVICO HDTV5 PCI Nano [18ac:d530] + 59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 23b58bc9cf2b..a1756c6c6dca 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1402,7 +1402,8 @@ static const struct cx88_board cx88_boards[] = { .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO] = { - .name = "DVICO HDTV5 PCI Nano", + .name = "DViCO FusionHDTV 5 PCI nano", + /* xc3008 tuner, digital only for now */ .tuner_type = TUNER_ABSENT, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, diff --git a/drivers/media/video/cx88/cx88-video.c b/drivers/media/video/cx88/cx88-video.c index c30356bb35e9..191577d166aa 100644 --- a/drivers/media/video/cx88/cx88-video.c +++ b/drivers/media/video/cx88/cx88-video.c @@ -1832,8 +1832,10 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev, switch (core->boardnr) { case CX88_BOARD_DVICO_FUSIONHDTV_5_GOLD: - request_module("ir-kbd-i2c"); request_module("rtc-isl1208"); + /* break intentionally omitted */ + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + request_module("ir-kbd-i2c"); } /* register v4l devices */ -- cgit v1.2.3 From 9507901ef329b2dd3417372c7c9b2abcfd5c1885 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:15 -0300 Subject: V4L/DVB (7257): cx88: Add xc2028/3028 boards This patch ports a patch from Markus Rechberger to work with tuner-xc2028. It adds entries for several cx88 boards with xc2038/3028 tuners. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 4 + drivers/media/video/cx88/cx88-cards.c | 188 +++++++++++++++++++++++++++++++- drivers/media/video/cx88/cx88-dvb.c | 44 +++++++- drivers/media/video/cx88/cx88.h | 4 + 4 files changed, 238 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 7d48e3dbd074..c92795b6e697 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -58,3 +58,7 @@ 57 -> ADS Tech Instant Video PCI [1421:0390] 58 -> Pinnacle PCTV HD 800i [11bd:0051] 59 -> DViCO FusionHDTV 5 PCI nano [18ac:d530] + 60 -> Pinnacle Hybrid PCTV [12ab:1788] + 61 -> Winfast TV2000 XP Global [107d:6f18] + 62 -> PowerColor Real Angel 330 [14f1:ea3d] + 63 -> Geniatech X8000-MT DVBT [14f1:8852] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 3e07fbe4c843..d07286fa21f5 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1426,6 +1426,124 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_PINNACLE_HYBRID_PCTV] = { + .name = "Pinnacle Hybrid PCTV", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + }, + [CX88_BOARD_WINFAST_TV2000_XP_GLOBAL] = { + .name = "Winfast TV2000 XP Global", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio1 = 0x0000, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio1 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x004ff, + .gpio1 = 0x010ff, + .gpio2 = 0x0ff, + }, + }, + [CX88_BOARD_POWERCOLOR_REAL_ANGEL] = { + .name = "PowerColor Real Angel 330", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0400, /* pin 2:mute = 0 (off?) */ + .gpio1 = 0x0000, + .gpio2 = 0x0800, /* pin 19:audio = 0 (tv) */ + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x0400, /* probably? or 0x0404 to turn mute on */ + .gpio1 = 0x0000, + .gpio2 = 0x0808, /* pin 19:audio = 1 (line) */ + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000ff, + .gpio1 = 0x0f37d, + .gpio2 = 0x00019, + .gpio3 = 0x00000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000ff, + .gpio1 = 0x0f35d, + .gpio2 = 0x00019, + .gpio3 = 0x00000, + }, + }, + [CX88_BOARD_GENIATECH_X8000_MT] = { + /* Also PowerColor Real Angel 330 and Geniatech X800 OEM */ + .name = "Geniatech X8000-MT DVBT", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e341, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e361, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e361, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x00000000, + .gpio1 = 0x00e3e341, + .gpio2 = 0x00000000, + .gpio3 = 0x00000000, + }, + .mpeg = CX88_MPEG_DVB, + } }; /* ------------------------------------------------------------------ */ @@ -1743,7 +1861,23 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x18ac, .subdevice = 0xd530, .card = CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO, - }, + }, { + .subvendor = 0x12ab, + .subdevice = 0x1788, + .card = CX88_BOARD_PINNACLE_HYBRID_PCTV, + }, { + .subvendor = 0x14f1, + .subdevice = 0xea3d, + .card = CX88_BOARD_POWERCOLOR_REAL_ANGEL, + }, { + .subvendor = 0x107d, + .subdevice = 0x6f18, + .card = CX88_BOARD_WINFAST_TV2000_XP_GLOBAL, + }, { + .subvendor = 0x14f1, + .subdevice = 0x8852, + .card = CX88_BOARD_GENIATECH_X8000_MT, + } }; /* ----------------------------------------------------------------------- */ @@ -1875,6 +2009,50 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) CX88_RADIO : 0; } +/* ----------------------------------------------------------------------- */ +/* some Geniatech specific stuff */ + +static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mode) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + switch (command) { + case XC2028_TUNER_RESET: + switch (INPUT(core->input).type) { + case CX88_RADIO: + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + cx_write(MO_GP1_IO, 0x101000); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + return 0; + case CX88_VMUX_DVB: + cx_write(MO_GP1_IO, 0x030302); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + cx_write(MO_GP1_IO, 0x101000); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + return 0; + default: + cx_write(MO_GP1_IO, 0x030301); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + cx_write(MO_GP1_IO, 0x101000); + mdelay(50); + cx_write(MO_GP1_IO, 0x101010); + mdelay(50); + return 0; + } + } + return -EINVAL; +} + /* ----------------------------------------------------------------------- */ /* some DViCO specific stuff */ @@ -1914,6 +2092,14 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) struct i2c_algo_bit_data *i2c_algo = priv; struct cx88_core *core = i2c_algo->data; + /* Board-specific callbacks */ + switch (core->boardnr) { + case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + case CX88_BOARD_GENIATECH_X8000_MT: + return cx88_xc3028_geniatech_tuner_callback(priv, command, arg); + } + switch (command) { case XC2028_TUNER_RESET: { diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 735376060df2..c786d951a04b 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -434,8 +434,16 @@ static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .tuner_callback = cx88_tuner_callback, }; +static struct zl10353_config cx88_geniatech_x8000_mt = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, +}; + + static int dvb_register(struct cx8802_dev *dev) { + int attach_xc3028 = 0; + /* init struct videobuf_dvb */ dev->dvb.name = dev->core->name; dev->ts_gen_cntrl = 0x0c; @@ -727,16 +735,50 @@ static int dvb_register(struct cx8802_dev *dev) fe->ops.tuner_ops.set_config(fe, &ctl); } break; + case CX88_BOARD_PINNACLE_HYBRID_PCTV: + dev->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_geniatech_x8000_mt, + &dev->core->i2c_adap); + attach_xc3028 = 1; + break; + case CX88_BOARD_GENIATECH_X8000_MT: + dev->ts_gen_cntrl = 0x00; + + dev->dvb.frontend = dvb_attach(zl10353_attach, + &cx88_geniatech_x8000_mt, + &dev->core->i2c_adap); + attach_xc3028 = 1; + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); break; } if (NULL == dev->dvb.frontend) { - printk(KERN_ERR "%s/2: frontend initialization failed\n", dev->core->name); + printk(KERN_ERR + "%s/2: frontend initialization failed\n", + dev->core->name); return -1; } + if (attach_xc3028) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->core->i2c_adap, + .i2c_addr = 0x61, + .video_dev = dev->core, + }; + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc3028 attach failed\n", + dev->core->name); + dvb_frontend_detach(dev->dvb.frontend); + dvb_unregister_frontend(dev->dvb.frontend); + dev->dvb.frontend = NULL; + return -1; + } + } + /* Ensure all frontends negotiate bus access */ dev->dvb.frontend->ops.ts_bus_ctrl = cx88_dvb_bus_ctrl; diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 8121bd07a88a..5145bf2f5557 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -212,6 +212,10 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_ADSTECH_PTV_390 57 #define CX88_BOARD_PINNACLE_PCTV_HD_800i 58 #define CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO 59 +#define CX88_BOARD_PINNACLE_HYBRID_PCTV 60 +#define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61 +#define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62 +#define CX88_BOARD_GENIATECH_X8000_MT 63 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From b3fb91d20ca111316854a166ff88b0c8c0f2388b Mon Sep 17 00:00:00 2001 From: Chris Pascoe Date: Tue, 22 Apr 2008 14:45:15 -0300 Subject: V4L/DVB (7258): Support DVB-T tuning on the DViCO FusionHDTV DVB-T Pro Add support for tuning DVB-T channels on DViCO's FusionHDTV DVB-T Pro board. The IR remote and analog tuner are not supported at this time. Some changes made by Mauro Chehab to allow merging it with some other xc3028 patches. Signed-off-by: Chris Pascoe Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 65 ++++++++++++++++++++++++++++++--- drivers/media/video/cx88/cx88-dvb.c | 23 ++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 4 files changed, 85 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index c92795b6e697..423da1543815 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -62,3 +62,4 @@ 61 -> Winfast TV2000 XP Global [107d:6f18] 62 -> PowerColor Real Angel 330 [14f1:ea3d] 63 -> Geniatech X8000-MT DVBT [14f1:8852] + 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index d07286fa21f5..1dc70f27f7f9 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1543,7 +1543,24 @@ static const struct cx88_board cx88_boards[] = { .gpio3 = 0x00000000, }, .mpeg = CX88_MPEG_DVB, - } + }, + [CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO] = { + .name = "DViCO FusionHDTV DVB-T PRO", + .tuner_type = TUNER_ABSENT, /* XXX: Has XC3028 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = { { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000067df, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000067df, + } }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -1748,7 +1765,11 @@ static const struct cx88_subid cx88_subids[] = { .subdevice = 0xdb11, .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS, /* Re-branded DViCO: UltraView DVB-T Plus */ - },{ + }, { + .subvendor = 0x18ac, + .subdevice = 0xdb30, + .card = CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO, + }, { .subvendor = 0x17de, .subdevice = 0x0840, .card = CX88_BOARD_KWORLD_HARDWARE_MPEG_TV_XPERT, @@ -2009,6 +2030,28 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) CX88_RADIO : 0; } +/* ------------------------------------------------------------------- */ +/* some Divco specific stuff */ +static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg) +{ + struct cx88_core *core = ptr; + + switch (command) { + case XC2028_TUNER_RESET: + cx_set(MO_GP0_IO, 0x0200); + cx_clear(MO_GP0_IO, 0x02); + mdelay(100); + cx_set(MO_GP0_IO, 0x02); + mdelay(100); + break; + default: + return -EINVAL; + } + + return 0; +} + + /* ----------------------------------------------------------------------- */ /* some Geniatech specific stuff */ @@ -2098,6 +2141,8 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: return cx88_xc3028_geniatech_tuner_callback(priv, command, arg); + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + return cx88_dvico_xc2028_callback(priv, command, arg); } switch (command) { @@ -2267,6 +2312,7 @@ static void cx88_card_setup(struct cx88_core *core) case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T1: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PLUS: case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_HYBRID: + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: /* GPIO0:0 is hooked to mt352 reset pin */ cx_set(MO_GP0_IO, 0x00000101); cx_clear(MO_GP0_IO, 0x00000001); @@ -2338,9 +2384,18 @@ static void cx88_card_setup(struct cx88_core *core) ctl.fname = XC2028_DEFAULT_FIRMWARE; ctl.max_len = 64; - /* FIXME: Those should be device-dependent */ - ctl.demod = XC3028_FE_OREN538; - ctl.mts = 1; + + switch (core->boardnr) { + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + ctl.scode_table = XC3028_FE_ZARLINK456; + break; + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + ctl.demod = XC3028_FE_OREN538; + break; + default: + ctl.demod = XC3028_FE_OREN538; + ctl.mts = 1; + } xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index c786d951a04b..591037d8d14f 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -237,6 +237,19 @@ static struct zl10353_config dvico_fusionhdtv_hybrid = { .no_tuner = 1, }; +static struct zl10353_config dvico_fusionhdtv_xc3028 = { + .demod_address = 0x0f, + .if2 = 45600, + .no_tuner = 1, +}; + +static struct mt352_config dvico_fusionhdtv_mt352_xc3028 = { + .demod_address = 0x0f, + .if2 = 4560, + .no_tuner = 1, + .demod_init = dvico_fusionhdtv_demod_init, +}; + static struct zl10353_config dvico_fusionhdtv_plus_v1_1 = { .demod_address = 0x0f, }; @@ -567,6 +580,16 @@ static int dvb_register(struct cx8802_dev *dev) DVB_PLL_THOMSON_FE6600); } break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + dev->dvb.frontend = dvb_attach(zl10353_attach, + &dvico_fusionhdtv_xc3028, + &dev->core->i2c_adap); + if (dev->dvb.frontend == NULL) + dev->dvb.frontend = dvb_attach(mt352_attach, + &dvico_fusionhdtv_mt352_xc3028, + &dev->core->i2c_adap); + attach_xc3028 = 1; + break; case CX88_BOARD_PCHDTV_HD3000: dev->dvb.frontend = dvb_attach(or51132_attach, &pchdtv_hd3000, &dev->core->i2c_adap); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 5145bf2f5557..9df3f198a4df 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -216,6 +216,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_WINFAST_TV2000_XP_GLOBAL 61 #define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62 #define CX88_BOARD_GENIATECH_X8000_MT 63 +#define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From bc36a686a65dd9b941463ff894a3868c62851186 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:45:27 -0300 Subject: V4L/DVB (7262): Add support for xc3028-based boards This patch adds support for the following saa7134 xc3028 based boards: 132 -> AVerMedia Cardbus TV/Radio (E506R) [1461:f436] 133 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936] 134 -> Avermedia M115 [1461:a836] 135 -> Compro VideoMate T750 [185b:c900] This is based on a original patch thanks to Markus Rechberger that added xc3028 gpio init code for the above boards. This patch moves saa7134_tuner_callback to saa7134-cards, originally used only by tda8290 DVB-S boards. The callback was made more generic to support other tuners. Currently, it supports both tda8290 and xc2028/xc3028 tuners. Added also the basis for xc5000 tuner callback. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 4 + drivers/media/video/saa7134/saa7134-cards.c | 230 ++++++++++++++++++++++++++-- drivers/media/video/saa7134/saa7134-core.c | 34 ---- drivers/media/video/saa7134/saa7134-dvb.c | 32 ++++ drivers/media/video/saa7134/saa7134.h | 7 +- 5 files changed, 259 insertions(+), 48 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index 765a06b1f0f6..c1f9f138d1bb 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -134,3 +134,7 @@ 133 -> NXP Snake DVB-S reference design 134 -> Medion/Creatix CTX953 Hybrid [16be:0010] 135 -> MSI TV@nywhere A/D v1.1 [1462:8625] +136 -> AVerMedia Cardbus TV/Radio (E506R) [1461:f436] +137 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936] +138 -> Avermedia M115 [1461:a836] +139 -> Compro VideoMate T750 [185b:c900] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index f9c85b7cba1a..6fde042ee317 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -22,9 +22,12 @@ #include #include +#include +#include #include "saa7134-reg.h" #include "saa7134.h" +#include "tuner-xc2028.h" #include #include @@ -4064,6 +4067,97 @@ struct saa7134_board saa7134_boards[] = { .gpio = 0x0200000, }, }, + [SAA7134_BOARD_AVERMEDIA_CARDBUS_506] = { + .name = "AVerMedia Cardbus TV/Radio (E506R)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + /* + TODO: + .mpeg = SAA7134_MPEG_DVB, + */ + + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = TV, + }, + }, + [SAA7134_BOARD_AVERMEDIA_A16D] = { + .name = "AVerMedia Hybrid TV/Radio (A16D)", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE1, + } }, + .radio = { + .name = name_radio, + .amux = LINE1, + }, + }, + [SAA7134_BOARD_AVERMEDIA_M115] = { + .name = "Avermedia M115", + .audio_clock = 0x187de7, + .tuner_type = TUNER_XC2028, + .inputs = {{ + .name = name_tv, + .vmux = 1, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 3, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + }, + [SAA7134_BOARD_VIDEOMATE_T750] = { + /* John Newbigin */ + .name = "Compro VideoMate T750", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_XC2028, + .mpeg = SAA7134_MPEG_DVB, + .inputs = {{ + .name = name_tv, + .vmux = 3, + .amux = TV, + .tv = 1, + }, { + .name = name_comp1, + .vmux = 1, + .amux = LINE2, + }, { + .name = name_svideo, + .vmux = 8, + .amux = LINE2, + } }, + .radio = { + .name = name_radio, + .amux = TV, + } + } }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -5027,6 +5121,30 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0x8625, /* TV@nywhere A/D v1.1 */ .driver_data = SAA7134_BOARD_MSI_TVANYWHERE_AD11, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf436, + .driver_data = SAA7134_BOARD_AVERMEDIA_CARDBUS_506, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xf936, + .driver_data = SAA7134_BOARD_AVERMEDIA_A16D, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa836, + .driver_data = SAA7134_BOARD_AVERMEDIA_M115, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x185b, + .subdevice = 0xc900, + .driver_data = SAA7134_BOARD_VIDEOMATE_T750, + }, { /* --- boards without eeprom + subsystem ID --- */ .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7134, @@ -5082,6 +5200,67 @@ static void board_flyvideo(struct saa7134_dev *dev) dev->name, dev->name, dev->name); } +static int saa7134_xc2028_callback(struct saa7134_dev *dev, + int command, int arg) +{ + switch (command) { + case XC2028_TUNER_RESET: + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x06e20000, 0x06e20000); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x06a20000, 0x06a20000); + saa_andorl(SAA7133_ANALOG_IO_SELECT >> 2, 0x02, 0x02); + saa_andorl(SAA7134_ANALOG_IN_CTRL1 >> 2, 0x81, 0x81); + saa_andorl(SAA7134_AUDIO_CLOCK0 >> 2, 0x03187de7, 0x03187de7); + saa_andorl(SAA7134_AUDIO_PLL_CTRL >> 2, 0x03, 0x03); + saa_andorl(SAA7134_AUDIO_CLOCKS_PER_FIELD0 >> 2, + 0x0001e000, 0x0001e000); + return 0; + } + return -EINVAL; +} + + +static int saa7134_tda8290_callback(struct saa7134_dev *dev, + int command, int arg) +{ + u8 sync_control; + + switch (command) { + case 0: /* switch LNA gain through GPIO 22*/ + saa7134_set_gpio(dev, 22, arg) ; + break; + case 1: /* vsync output at GPIO22. 50 / 60Hz */ + saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80); + saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03); + if (arg == 1) + sync_control = 11; + else + sync_control = 17; + saa_writeb(SAA7134_VGATE_START, sync_control); + saa_writeb(SAA7134_VGATE_STOP, sync_control + 1); + saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00); + break; + default: + return -EINVAL; + } + + return 0; +} + +int saa7134_tuner_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct saa7134_dev *dev = i2c_algo->data; + + switch (dev->tuner_type) { + case TUNER_PHILIPS_TDA8290: + return saa7134_tda8290_callback(dev, command, arg); + case TUNER_XC2028: + return saa7134_xc2028_callback(dev, command, arg); + } + return -EINVAL; +} +EXPORT_SYMBOL(saa7134_tuner_callback); + /* ----------------------------------------------------------- */ static void hauppauge_eeprom(struct saa7134_dev *dev, u8 *eeprom_data) @@ -5151,6 +5330,7 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_VIDEOMATE_DVBT_300: case SAA7134_BOARD_VIDEOMATE_DVBT_200: case SAA7134_BOARD_VIDEOMATE_DVBT_200A: + case SAA7134_BOARD_VIDEOMATE_T750: case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: case SAA7134_BOARD_BEHOLD_409FM: @@ -5217,6 +5397,8 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x08000000, 0x00000000); break; case SAA7134_BOARD_AVERMEDIA_CARDBUS: + case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + case SAA7134_BOARD_AVERMEDIA_M115: case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: /* power-up tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0xffffffff); @@ -5284,11 +5466,16 @@ int saa7134_board_init2(struct saa7134_dev *dev) dev->tuner_type = saa7134_boards[dev->board].tuner_type; if (TUNER_ABSENT != dev->tuner_type) { - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; - tun_setup.type = dev->tuner_type; - tun_setup.addr = ADDR_UNSET; + tun_setup.mode_mask = T_RADIO | + T_ANALOG_TV | + T_DIGITAL_TV; + tun_setup.type = dev->tuner_type; + tun_setup.addr = ADDR_UNSET; + tun_setup.tuner_callback = saa7134_tuner_callback; - saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR, &tun_setup); + saa7134_i2c_call_clients(dev, + TUNER_SET_TYPE_ADDR, + &tun_setup); } break; case SAA7134_BOARD_MD7134: @@ -5359,11 +5546,14 @@ int saa7134_board_init2(struct saa7134_dev *dev) &tda9887_cfg); } - tun_setup.mode_mask = T_RADIO | T_ANALOG_TV | T_DIGITAL_TV; + tun_setup.mode_mask = T_RADIO | + T_ANALOG_TV | + T_DIGITAL_TV; tun_setup.type = dev->tuner_type; tun_setup.addr = ADDR_UNSET; - saa7134_i2c_call_clients (dev, TUNER_SET_TYPE_ADDR,&tun_setup); + saa7134_i2c_call_clients(dev, + TUNER_SET_TYPE_ADDR, &tun_setup); } break; case SAA7134_BOARD_PHILIPS_EUROPA: @@ -5496,12 +5686,26 @@ int saa7134_board_init2(struct saa7134_dev *dev) } break; } + + if (dev->tuner_type == TUNER_XC2028) { + struct v4l2_priv_tun_config xc2028_cfg; + struct xc2028_ctrl ctl; + + memset(&xc2028_cfg, 0, sizeof(ctl)); + memset(&ctl, 0, sizeof(ctl)); + + ctl.fname = XC2028_DEFAULT_FIRMWARE; + ctl.max_len = 64; + + /* FIXME: This should be device-dependent */ + ctl.demod = XC3028_FE_OREN538; + ctl.mts = 1; + + xc2028_cfg.tuner = TUNER_XC2028; + xc2028_cfg.priv = &ctl; + + saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &xc2028_cfg); + } + return 0; } - -/* ----------------------------------------------------------- */ -/* - * Local variables: - * c-basic-offset: 8 - * End: - */ diff --git a/drivers/media/video/saa7134/saa7134-core.c b/drivers/media/video/saa7134/saa7134-core.c index 4817a0e046a8..ed96ce775a9b 100644 --- a/drivers/media/video/saa7134/saa7134-core.c +++ b/drivers/media/video/saa7134/saa7134-core.c @@ -142,40 +142,6 @@ void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value) } } -int saa7134_tuner_callback(void *ptr, int command, int arg) -{ - u8 sync_control; - struct i2c_algo_bit_data *i2c_algo = priv; - struct saa7134_dev *dev = i2c_algo->data; - - switch (dev->tuner_type) { - case TUNER_PHILIPS_TDA8290: - switch (command) { - case 0: /* switch LNA gain through GPIO 22*/ - saa7134_set_gpio(dev, 22, arg) ; - break; - case 1: /* vsync output at GPIO22. 50 / 60Hz */ - dprintk("setting GPIO22 to vsync %d\n", arg); - saa_andorb(SAA7134_VIDEO_PORT_CTRL3, 0x80, 0x80); - saa_andorb(SAA7134_VIDEO_PORT_CTRL6, 0x0f, 0x03); - if (arg == 1) - sync_control = 11; - else - sync_control = 17; - saa_writeb(SAA7134_VGATE_START, sync_control); - saa_writeb(SAA7134_VGATE_STOP, sync_control + 1); - saa_andorb(SAA7134_MISC_VGATE_MSB, 0x03, 0x00); - break; - default: - return -EINVAL; - } - break; - default: - return -ENODEV; - } - return 0; -} - /* ------------------------------------------------------------------ */ diff --git a/drivers/media/video/saa7134/saa7134-dvb.c b/drivers/media/video/saa7134/saa7134-dvb.c index eabc67d03b2c..97d9178dca2b 100644 --- a/drivers/media/video/saa7134/saa7134-dvb.c +++ b/drivers/media/video/saa7134/saa7134-dvb.c @@ -38,6 +38,7 @@ #include "mt352_priv.h" /* FIXME */ #include "tda1004x.h" #include "nxt200x.h" +#include "tuner-xc2028.h" #include "tda10086.h" #include "tda826x.h" @@ -190,6 +191,11 @@ static struct mt352_config avermedia_777 = { .demod_init = mt352_aver777_init, }; +static struct mt352_config avermedia_e506r_mt352_dev = { + .demod_address = (0x1e >> 1), + .no_tuner = 1, +}; + /* ================================================================== * tda1004x based DVB-T cards, helper functions */ @@ -895,6 +901,8 @@ static struct nxt200x_config kworldatsc110 = { static int dvb_init(struct saa7134_dev *dev) { int ret; + int attach_xc3028 = 0; + /* init struct videobuf_dvb */ dev->ts.nr_bufs = 32; dev->ts.nr_packets = 32*4; @@ -1142,11 +1150,35 @@ static int dvb_init(struct saa7134_dev *dev) case SAA7134_BOARD_MSI_TVANYWHERE_AD11: configure_tda827x_fe(dev, &philips_tiger_s_config); break; + case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: + dev->dvb.frontend = dvb_attach(mt352_attach, + &avermedia_e506r_mt352_dev, + &dev->i2c_adap); + attach_xc3028 = 1; + break; default: wprintk("Huh? unknown DVB card?\n"); break; } + if (attach_xc3028) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->i2c_adap, + .i2c_addr = 0x61, + .video_dev = dev, + }; + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); + if (!fe) { + printk(KERN_ERR "%s/2: xc3028 attach failed\n", + dev->name); + dvb_frontend_detach(dev->dvb.frontend); + dvb_unregister_frontend(dev->dvb.frontend); + dev->dvb.frontend = NULL; + return -1; + } + } + if (NULL == dev->dvb.frontend) { printk(KERN_ERR "%s/dvb: frontend initialization failed\n", dev->name); return -1; diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index d7e0781fe8a1..ba88a1093d14 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -257,6 +257,11 @@ struct saa7134_format { #define SAA7134_BOARD_PHILIPS_SNAKE 133 #define SAA7134_BOARD_CREATIX_CTX953 134 #define SAA7134_BOARD_MSI_TVANYWHERE_AD11 135 +#define SAA7134_BOARD_AVERMEDIA_CARDBUS_506 136 +#define SAA7134_BOARD_AVERMEDIA_A16D 137 +#define SAA7134_BOARD_AVERMEDIA_M115 138 +#define SAA7134_BOARD_VIDEOMATE_T750 139 + #define SAA7134_MAXBOARDS 8 #define SAA7134_INPUT_MAX 8 @@ -599,7 +604,6 @@ extern int saa7134_no_overlay; void saa7134_track_gpio(struct saa7134_dev *dev, char *msg); void saa7134_set_gpio(struct saa7134_dev *dev, int bit_no, int value); -int saa7134_tuner_callback(void *ptr, int command, int arg); #define SAA7134_PGTABLE_SIZE 4096 @@ -636,6 +640,7 @@ extern struct pci_device_id __devinitdata saa7134_pci_tbl[]; extern int saa7134_board_init1(struct saa7134_dev *dev); extern int saa7134_board_init2(struct saa7134_dev *dev); +int saa7134_tuner_callback(void *priv, int command, int arg); /* ----------------------------------------------------------- */ -- cgit v1.2.3 From 1117d6ba1313b8821b10403de114c38764008c45 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 22 Apr 2008 14:45:34 -0300 Subject: V4L/DVB (7287): cx88: add analog support for DVICO FusionHDTV7 Gold Signed-off-by: Steven Toth Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 40 +++++++++++++++++++++++++++++++++ drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 42 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index 423da1543815..b5f2134f1664 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -63,3 +63,4 @@ 62 -> PowerColor Real Angel 330 [14f1:ea3d] 63 -> Geniatech X8000-MT DVBT [14f1:8852] 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] + 65 -> DVICO FusionHDTV7 Gold [18ac:d610] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index bf58f350e269..8e29e48a86f3 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1571,6 +1571,26 @@ static const struct cx88_board cx88_boards[] = { } }, .mpeg = CX88_MPEG_DVB, }, + [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = { + .name = "DVICO FusionHDTV7 Gold", + .tuner_type = TUNER_XC5000, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = {{ + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x37df, + },{ + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x37df, + },{ + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x37df, + }}, + }, }; /* ------------------------------------------------------------------ */ @@ -1908,6 +1928,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x14f1, .subdevice = 0x8852, .card = CX88_BOARD_GENIATECH_X8000_MT, + },{ + .subvendor = 0x18ac, + .subdevice = 0xd610, + .card = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD, } }; @@ -2189,6 +2213,18 @@ static int cx88_xc5000_tuner_callback(void *priv, int command, int arg) return -EINVAL; } break; + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + if (command == 0) { /* This is the reset command from xc5000 */ + cx_clear(MO_GP0_IO, 0x00000010); + msleep(10); + cx_set(MO_GP0_IO, 0x00000010); + return 0; + } else { + printk(KERN_ERR + "xc5000: unknown tuner callback command.\n"); + return -EINVAL; + } + break; } return 0; /* Should never be here */ } @@ -2255,6 +2291,10 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ udelay(1000); break; + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: + /* Enable the xc5000 tuner */ + cx_set(MO_GP0_IO, 0x00001010); + break; } } diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 9df3f198a4df..85a95a0a94d9 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -217,6 +217,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_POWERCOLOR_REAL_ANGEL 62 #define CX88_BOARD_GENIATECH_X8000_MT 63 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 +#define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 76464d412a5a51633881078d4109212e4463e8d4 Mon Sep 17 00:00:00 2001 From: Michael Krufky Date: Tue, 22 Apr 2008 14:45:35 -0300 Subject: V4L/DVB (7288): cx88: fix GPIO for FusionHDTV 7 Gold input selection Fix GPIO for FusionHDTV 7 Gold tv / s-video / composite input selection. Fix card textual name to match other FusionHDTV device names. Signed-off-by: Michael Krufky Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 2 +- drivers/media/video/cx88/cx88-cards.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index b5f2134f1664..da7f70dfad2a 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -63,4 +63,4 @@ 62 -> PowerColor Real Angel 330 [14f1:ea3d] 63 -> Geniatech X8000-MT DVBT [14f1:8852] 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] - 65 -> DVICO FusionHDTV7 Gold [18ac:d610] + 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 8e29e48a86f3..7a2b0f26921a 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1572,7 +1572,7 @@ static const struct cx88_board cx88_boards[] = { .mpeg = CX88_MPEG_DVB, }, [CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD] = { - .name = "DVICO FusionHDTV7 Gold", + .name = "DViCO FusionHDTV 7 Gold", .tuner_type = TUNER_XC5000, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, @@ -1580,15 +1580,15 @@ static const struct cx88_board cx88_boards[] = { .input = {{ .type = CX88_VMUX_TELEVISION, .vmux = 0, - .gpio0 = 0x37df, + .gpio0 = 0x10df, },{ .type = CX88_VMUX_COMPOSITE1, .vmux = 1, - .gpio0 = 0x37df, + .gpio0 = 0x16d9, },{ .type = CX88_VMUX_SVIDEO, .vmux = 2, - .gpio0 = 0x37df, + .gpio0 = 0x16d9, }}, }, }; -- cgit v1.2.3 From 97275ac514c7f1131f42f8b06e073b144c744e78 Mon Sep 17 00:00:00 2001 From: Ernesto Hernández-Novich Date: Tue, 22 Apr 2008 14:45:58 -0300 Subject: V4L/DVB (7366): Support for a 16-channel bt878 card MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I have what looks like a Geovision GV-600 (or 650) card. It has a large chip in the middle labeled CONEXANT FUSION 878A 25878-13 E345881.1 0312 TAIWAN It has an audio connector coming out from a chip labeled ATMEL 0242 AT89C2051-24PI It is identified as follows on my Debian GNU/Linux Etch (kernel 2.6.18) ... 01:0a.0 Multimedia video controller: Brooktree Corporation Bt878 Video Capture (rev 11) 01:0a.1 Multimedia controller: Brooktree Corporation Bt878 Audio Capture (rev 11) ... 01:0a.0 0400: 109e:036e (rev 11) Subsystem: 008a:763c Flags: bus master, medium devsel, latency 64, IRQ 58 Memory at dfffe000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 01:0a.1 0480: 109e:0878 (rev 11) Subsystem: 008a:763c Flags: bus master, medium devsel, latency 64, IRQ 58 Memory at dffff000 (32-bit, prefetchable) [size=4K] Capabilities: [44] Vital Product Data Capabilities: [4c] Power Management version 2 It was being detected as a GENERIC UNKNOWN CARD both by the 2.6.18 kernel and the latest v4l-dvb drivers, but it did not work at all. The card has sixteen (16) BNC video inputs, four of them on the board itself and twelve on three daughter-cards. It has a single bt878 chip, no tuner and what looks like and audio input. After doing some research I managed to get only eight channels working by forcing card=125 and those DID NOT match channels 0-7 on the card, and no audio. Based on what was working for card=125, I added the card definition block, added a specific muxsel routine and got the card working fully with xawtv, where the sixteen channels show up as Composite0 to Composite15, matching the channel labels in the card and daughter-cards. I have made no efforts yet to get audio working, but would appreciate any pointers. Signed-off-by: Ernesto Hernández-Novich Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/video/bt8xx/bttv-cards.c | 28 ++++++++++++++++++++++++++++ drivers/media/video/bt8xx/bttv.h | 1 + 3 files changed, 30 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index d97cf7cc6088..17911d038765 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -148,3 +148,4 @@ 147 -> VoodooTV 200 (USA) [121a:3000] 148 -> DViCO FusionHDTV 2 [dbc0:d200] 149 -> Typhoon TV-Tuner PCI (50684) +150 -> Geovision GV-600 [008a:763c] diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index b963bde97412..417dd552dba9 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -71,6 +71,8 @@ static void kodicom4400r_init(struct bttv *btv); static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input); static void sigmaSQ_muxsel(struct bttv *btv, unsigned int input); +static void geovision_muxsel(struct bttv *btv, unsigned int input); + static int terratec_active_radio_upgrade(struct bttv *btv); static int tea5757_read(struct bttv *btv); static int tea5757_write(struct bttv *btv, int value); @@ -301,6 +303,7 @@ static struct CARD { { 0xd50018ac, BTTV_BOARD_DVICO_FUSIONHDTV_5_LITE, "DViCO FusionHDTV 5 Lite" }, { 0x00261822, BTTV_BOARD_TWINHAN_DST, "DNTV Live! Mini "}, { 0xd200dbc0, BTTV_BOARD_DVICO_FUSIONHDTV_2, "DViCO FusionHDTV 2" }, + { 0x763c008a, BTTV_BOARD_GEOVISION_GV600, "GeoVision GV-600" }, { 0, -1, NULL } }; @@ -2994,6 +2997,24 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, + [BTTV_BOARD_GEOVISION_GV600] = { + /* emhn@usb.ve */ + .name = "Geovision GV-600", + .video_inputs = 16, + .audio_inputs = 0, + .tuner = UNSET, + .svhs = UNSET, + .gpiomask = 0x0, + .muxsel = { 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2 }, + .muxsel_hook = geovision_muxsel, + .gpiomux = { 0 }, + .no_msp34xx = 1, + .pll = PLL_28, + .tuner_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); @@ -3333,6 +3354,13 @@ static void sigmaSLC_muxsel(struct bttv *btv, unsigned int input) gpio_bits( 3<<9, inmux<<9 ); } +static void geovision_muxsel(struct bttv *btv, unsigned int input) +{ + unsigned int inmux = input % 16; + gpio_inout(0xf, 0xf); + gpio_bits(0xf, inmux); +} + /* ----------------------------------------------------------------------- */ static void bttv_reset_audio(struct bttv *btv) diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index bf4c339a520c..ed0cd3b1a01e 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -173,6 +173,7 @@ #define BTTV_BOARD_VOODOOTV_200 0x93 #define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94 #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 +#define BTTV_BOARD_GEOVISION_GV600 0x96 /* more card-specific defines */ -- cgit v1.2.3 From e80faad3d7a332b7fe5a72dd64a81d28dd5c2e44 Mon Sep 17 00:00:00 2001 From: Mauro Lacy Date: Tue, 22 Apr 2008 14:45:58 -0300 Subject: V4L/DVB (7368): bttv: added support for Kozumi KTV-01C card Signed-off-by: Mauro Lacy Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.bttv | 1 + drivers/media/common/ir-keymaps.c | 8 +++++++- drivers/media/video/bt8xx/bttv-cards.c | 23 +++++++++++++++++++++++ drivers/media/video/bt8xx/bttv-input.c | 6 ++++++ drivers/media/video/bt8xx/bttv.h | 1 + 5 files changed, 38 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.bttv b/Documentation/video4linux/CARDLIST.bttv index 17911d038765..f32efb6fb12c 100644 --- a/Documentation/video4linux/CARDLIST.bttv +++ b/Documentation/video4linux/CARDLIST.bttv @@ -149,3 +149,4 @@ 148 -> DViCO FusionHDTV 2 [dbc0:d200] 149 -> Typhoon TV-Tuner PCI (50684) 150 -> Geovision GV-600 [008a:763c] +151 -> Kozumi KTV-01C diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 2ab5a120470d..107565c47274 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -1157,7 +1157,8 @@ EXPORT_SYMBOL_GPL(ir_codes_purpletv); /* Mapping for the 28 key remote control as seen at http://www.sednacomputer.com/photo/cardbus-tv.jpg - Pavel Mihaylov */ + Pavel Mihaylov + Also for the remote bundled with Kozumi KTV-01C card */ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [ 0x00 ] = KEY_0, [ 0x01 ] = KEY_1, @@ -1188,6 +1189,11 @@ IR_KEYTAB_TYPE ir_codes_pctv_sedna[IR_KEYTAB_SIZE] = { [ 0x1c ] = KEY_RADIO, /* FM Radio */ [ 0x1d ] = KEY_RECORD, [ 0x1e ] = KEY_PAUSE, + /* additional codes for Kozumi's remote */ + [0x14] = KEY_INFO, /* OSD */ + [0x16] = KEY_OK, /* OK */ + [0x17] = KEY_DIGITS, /* Plus */ + [0x1f] = KEY_PLAY, /* Play */ }; EXPORT_SYMBOL_GPL(ir_codes_pctv_sedna); diff --git a/drivers/media/video/bt8xx/bttv-cards.c b/drivers/media/video/bt8xx/bttv-cards.c index 417dd552dba9..22c2708e42ab 100644 --- a/drivers/media/video/bt8xx/bttv-cards.c +++ b/drivers/media/video/bt8xx/bttv-cards.c @@ -3015,6 +3015,29 @@ struct tvcard bttv_tvcards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, }, + [BTTV_BOARD_KOZUMI_KTV_01C] = { + /* Mauro Lacy + * Based on MagicTV and Conceptronic CONTVFMi */ + + .name = "Kozumi KTV-01C", + .video_inputs = 3, + .audio_inputs = 1, + .tuner = 0, + .svhs = 2, + .gpiomask = 0x008007, + .muxsel = { 2, 3, 1, 1 }, + .gpiomux = { 0, 1, 2, 2 }, /* CONTVFMi */ + /*gpiomux = { 0, 1, 2, 3 }, /* MagicTV */ + .gpiomute = 3, /* CONTVFMi */ + /*gpiomute = 4, /* MagicTV */ + .needs_tvaudio = 0, + .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, /* TCL MK3 */ + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .pll = PLL_28, + .has_radio = 1, + .has_remote = 1, + }, }; static const unsigned int bttv_num_tvcards = ARRAY_SIZE(bttv_tvcards); diff --git a/drivers/media/video/bt8xx/bttv-input.c b/drivers/media/video/bt8xx/bttv-input.c index fc9ecb21eec6..a38af98f4cae 100644 --- a/drivers/media/video/bt8xx/bttv-input.c +++ b/drivers/media/video/bt8xx/bttv-input.c @@ -278,6 +278,12 @@ int bttv_input_init(struct bttv *btv) ir->mask_keyup = 0x004000; ir->polling = 50; /* ms */ break; + case BTTV_BOARD_KOZUMI_KTV_01C: + ir_codes = ir_codes_pctv_sedna; + ir->mask_keycode = 0x001f00; + ir->mask_keyup = 0x006000; + ir->polling = 50; /* ms */ + break; } if (NULL == ir_codes) { dprintk(KERN_INFO "Ooops: IR config error [card=%d]\n", btv->c.type); diff --git a/drivers/media/video/bt8xx/bttv.h b/drivers/media/video/bt8xx/bttv.h index ed0cd3b1a01e..0c859d949c78 100644 --- a/drivers/media/video/bt8xx/bttv.h +++ b/drivers/media/video/bt8xx/bttv.h @@ -174,6 +174,7 @@ #define BTTV_BOARD_DVICO_FUSIONHDTV_2 0x94 #define BTTV_BOARD_TYPHOON_TVTUNERPCI 0x95 #define BTTV_BOARD_GEOVISION_GV600 0x96 +#define BTTV_BOARD_KOZUMI_KTV_01C 0x97 /* more card-specific defines */ -- cgit v1.2.3 From 2422a9b3f47c75d3915e6af78ebe25b7d2540262 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 22 Apr 2008 14:46:00 -0300 Subject: V4L/DVB (7370): Add basic support for Prolink Pixelview MPEG 8000GT TV reception ok. S-video and Composite not tested. Audio not tested. IR not implemented yet. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 70 +++++++++++++++++++++++++++++++-- drivers/media/video/cx88/cx88.h | 1 + 3 files changed, 68 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index da7f70dfad2a..a01991dcb317 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -64,3 +64,4 @@ 63 -> Geniatech X8000-MT DVBT [14f1:8852] 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] + 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 4c1e876a9232..98d3475a4b32 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -1591,6 +1591,29 @@ static const struct cx88_board cx88_boards[] = { .gpio0 = 0x16d9, }}, }, + [CX88_BOARD_PROLINK_PV_8000GT] = { + .name = "Prolink Pixelview MPEG 8000GT", + .tuner_type = TUNER_XC2028, + .tuner_addr = 0x61, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x0ff, + .gpio2 = 0x0cfb, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio2 = 0x0cfb, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio2 = 0x0cfb, + } }, + .radio = { + .type = CX88_RADIO, + .gpio2 = 0x0cfb, + }, + }, }; /* ------------------------------------------------------------------ */ @@ -1928,11 +1951,15 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x14f1, .subdevice = 0x8852, .card = CX88_BOARD_GENIATECH_X8000_MT, - },{ + }, { .subvendor = 0x18ac, .subdevice = 0xd610, .card = CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD, - } + }, { + .subvendor = 0x1554, + .subdevice = 0x4935, + .card = CX88_BOARD_PROLINK_PV_8000GT, + }, }; /* ----------------------------------------------------------------------- */ @@ -2063,9 +2090,10 @@ static void gdi_eeprom(struct cx88_core *core, u8 *eeprom_data) /* ------------------------------------------------------------------- */ /* some Divco specific stuff */ -static int cx88_dvico_xc2028_callback(void *ptr, int command, int arg) +static int cx88_dvico_xc2028_callback(void *priv, int command, int arg) { - struct cx88_core *core = ptr; + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; switch (command) { case XC2028_TUNER_RESET: @@ -2113,6 +2141,28 @@ static int cx88_xc3028_geniatech_tuner_callback(void *priv, int command, int mod return -EINVAL; } +/* ------------------------------------------------------------------- */ +/* some Divco specific stuff */ +static int cx88_pv_8000gt_callback(void *priv, int command, int arg) +{ + struct i2c_algo_bit_data *i2c_algo = priv; + struct cx88_core *core = i2c_algo->data; + + switch (command) { + case XC2028_TUNER_RESET: + cx_write(MO_GP2_IO, 0xcf7); + mdelay(50); + cx_write(MO_GP2_IO, 0xef5); + mdelay(50); + cx_write(MO_GP2_IO, 0xcf7); + break; + default: + return -EINVAL; + } + + return 0; +} + /* ----------------------------------------------------------------------- */ /* some DViCO specific stuff */ @@ -2159,6 +2209,8 @@ static int cx88_xc2028_tuner_callback(void *priv, int command, int arg) case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: return cx88_xc3028_geniatech_tuner_callback(priv, command, arg); + case CX88_BOARD_PROLINK_PV_8000GT: + return cx88_pv_8000gt_callback(priv, command, arg); case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: return cx88_dvico_xc2028_callback(priv, command, arg); } @@ -2291,6 +2343,16 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) cx_set(MO_GP0_IO, 0x00000080); /* 702 out of reset */ udelay(1000); break; + + case CX88_BOARD_PROLINK_PV_8000GT: + cx_write(MO_GP2_IO, 0xcf7); + mdelay(50); + cx_write(MO_GP2_IO, 0xef5); + mdelay(50); + cx_write(MO_GP2_IO, 0xcf7); + msleep(10); + break; + case CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD: /* Enable the xc5000 tuner */ cx_set(MO_GP0_IO, 0x00001010); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index 85a95a0a94d9..c0f4912793e9 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -218,6 +218,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_GENIATECH_X8000_MT 63 #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 +#define CX88_BOARD_PROLINK_PV_8000GT 66 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, -- cgit v1.2.3 From 99e09eac25f752b25f65392da7bd747b77040fea Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 27 Mar 2008 23:18:30 -0300 Subject: V4L/DVB (7448): Add support for Kworld ATSC 120 This board has a s5h1409 demod, plus a xc30x8 tuner (probably, xc3018). This patch adds proper support for radio, video, s-video, composite and ATSC. However, support for radio and video depends on having s5h1409 i2c gate open, otherwise, xc30x8 chip won't be visible. For a better support, some rework is needed on cx88 driver, to allow adding xc30x8 to i2c bus without sending i2c 0 byte reading to 0xc2 address. Thanks to Vanessa Ezekowitz for helping to figure out the proper parameters for s5h1409 and the GPIO pins used by each configuration. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx88 | 1 + drivers/media/video/cx88/cx88-cards.c | 110 ++++++++++++++++++++++++-------- drivers/media/video/cx88/cx88-dvb.c | 30 ++++++++- drivers/media/video/cx88/cx88.h | 3 + 4 files changed, 114 insertions(+), 30 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx88 b/Documentation/video4linux/CARDLIST.cx88 index a01991dcb317..543957346469 100644 --- a/Documentation/video4linux/CARDLIST.cx88 +++ b/Documentation/video4linux/CARDLIST.cx88 @@ -65,3 +65,4 @@ 64 -> DViCO FusionHDTV DVB-T PRO [18ac:db30] 65 -> DViCO FusionHDTV 7 Gold [18ac:d610] 66 -> Prolink Pixelview MPEG 8000GT [1554:4935] + 67 -> Kworld PlusTV HD PCI 120 (ATSC 120) [17de:08c1] diff --git a/drivers/media/video/cx88/cx88-cards.c b/drivers/media/video/cx88/cx88-cards.c index 6b83e3457b70..70505b4e5b46 100644 --- a/drivers/media/video/cx88/cx88-cards.c +++ b/drivers/media/video/cx88/cx88-cards.c @@ -27,7 +27,6 @@ #include "cx88.h" #include "tea5767.h" -#include "tuner-xc2028.h" static unsigned int tuner[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; static unsigned int radio[] = {[0 ... (CX88_MAXBOARDS - 1)] = UNSET }; @@ -1614,6 +1613,45 @@ static const struct cx88_board cx88_boards[] = { .gpio2 = 0x0cfb, }, }, + /* Both radio, analog and ATSC work with this board. + However, for analog to work, s5h1409 gate should be open, + otherwise, tuner-xc3028 won't be detected. + A proper fix require using the newer i2c methods to add + tuner-xc3028 without doing an i2c probe. + */ + [CX88_BOARD_KWORLD_ATSC_120] = { + .name = "Kworld PlusTV HD PCI 120 (ATSC 120)", + .tuner_type = TUNER_XC2028, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + .input = { { + .type = CX88_VMUX_TELEVISION, + .vmux = 0, + .gpio0 = 0x000000ff, + .gpio1 = 0x0000f35d, + .gpio2 = 0x00000000, + }, { + .type = CX88_VMUX_COMPOSITE1, + .vmux = 1, + .gpio0 = 0x000000ff, + .gpio1 = 0x0000f37e, + .gpio2 = 0x00000000, + }, { + .type = CX88_VMUX_SVIDEO, + .vmux = 2, + .gpio0 = 0x000000ff, + .gpio1 = 0x0000f37e, + .gpio2 = 0x00000000, + } }, + .radio = { + .type = CX88_RADIO, + .gpio0 = 0x000000ff, + .gpio1 = 0x0000f35d, + .gpio2 = 0x00000000, + }, + .mpeg = CX88_MPEG_DVB, + }, }; /* ------------------------------------------------------------------ */ @@ -1959,6 +1997,10 @@ static const struct cx88_subid cx88_subids[] = { .subvendor = 0x1554, .subdevice = 0x4935, .card = CX88_BOARD_PROLINK_PV_8000GT, + }, { + .subvendor = 0x17de, + .subdevice = 0x08c1, + .card = CX88_BOARD_KWORLD_ATSC_120, }, }; @@ -2200,6 +2242,7 @@ static int cx88_xc2028_tuner_callback(struct cx88_core *core, case CX88_BOARD_WINFAST_TV2000_XP_GLOBAL: case CX88_BOARD_POWERCOLOR_REAL_ANGEL: case CX88_BOARD_GENIATECH_X8000_MT: + case CX88_BOARD_KWORLD_ATSC_120: return cx88_xc3028_geniatech_tuner_callback(core, command, arg); case CX88_BOARD_PROLINK_PV_8000GT: @@ -2363,6 +2406,40 @@ static void cx88_card_setup_pre_i2c(struct cx88_core *core) } } +/* + * Sets board-dependent xc3028 configuration + */ +void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl) +{ + memset(ctl, 0, sizeof(*ctl)); + + ctl->fname = XC2028_DEFAULT_FIRMWARE; + ctl->max_len = 64; + + switch (core->boardnr) { + case CX88_BOARD_POWERCOLOR_REAL_ANGEL: + /* Doesn't work with firmware version 2.7 */ + ctl->fname = "xc3028-v25.fw"; + break; + case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: + ctl->scode_table = XC3028_FE_ZARLINK456; + break; + case CX88_BOARD_KWORLD_ATSC_120: + case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: + ctl->demod = XC3028_FE_OREN538; + break; + case CX88_BOARD_PROLINK_PV_8000GT: + /* + * This board uses non-MTS firmware + */ + break; + default: + ctl->demod = XC3028_FE_OREN538; + ctl->mts = 1; + } +} +EXPORT_SYMBOL_GPL(cx88_setup_xc3028); + static void cx88_card_setup(struct cx88_core *core) { static u8 eeprom[256]; @@ -2481,36 +2558,13 @@ static void cx88_card_setup(struct cx88_core *core) struct v4l2_priv_tun_config xc2028_cfg; struct xc2028_ctrl ctl; - memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); - memset(&ctl, 0, sizeof(ctl)); - - ctl.fname = XC2028_DEFAULT_FIRMWARE; - ctl.max_len = 64; - - switch (core->boardnr) { - case CX88_BOARD_POWERCOLOR_REAL_ANGEL: - /* Doesn't work with firmware version 2.7 */ - ctl.fname = "xc3028-v25.fw"; - break; - case CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO: - ctl.scode_table = XC3028_FE_ZARLINK456; - break; - case CX88_BOARD_DVICO_FUSIONHDTV_5_PCI_NANO: - ctl.demod = XC3028_FE_OREN538; - break; - case CX88_BOARD_PROLINK_PV_8000GT: - /* - * This board uses non-MTS firmware - */ - break; - default: - ctl.demod = XC3028_FE_OREN538; - ctl.mts = 1; - } + /* Fills device-dependent initialization parameters */ + cx88_setup_xc3028(core, &ctl); + /* Sends parameters to xc2028/3028 tuner */ + memset(&xc2028_cfg, 0, sizeof(xc2028_cfg)); xc2028_cfg.tuner = TUNER_XC2028; xc2028_cfg.priv = &ctl; - info_printk(core, "Asking xc2028/3028 to load firmware %s\n", ctl.fname); cx88_call_i2c_clients(core, TUNER_SET_CONFIG, &xc2028_cfg); diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index 8dca20b944dd..13cc395ca656 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -45,7 +45,6 @@ #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" -#include "tuner-xc2028.h" #include "tuner-xc2028-types.h" #include "tuner-simple.h" #include "tda9887.h" @@ -443,6 +442,16 @@ static struct s5h1409_config dvico_hdtv5_pci_nano_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, }; +static struct s5h1409_config kworld_atsc_120_config = { + .demod_address = 0x32 >> 1, + .qam_if = 44000, + .output_mode = S5H1409_SERIAL_OUTPUT, + .gpio = S5H1409_GPIO_OFF, + .inversion = S5H1409_INVERSION_OFF, + .status_mode = S5H1409_DEMODLOCKING, + .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, +}; + static struct xc5000_config pinnacle_pctv_hd_800i_tuner_config = { .i2c_address = 0x64, .if_khz = 5380, @@ -457,9 +466,12 @@ static struct zl10353_config cx88_geniatech_x8000_mt = { static int attach_xc3028(u8 addr, struct cx8802_dev *dev) { struct dvb_frontend *fe; + struct xc2028_ctrl ctl; struct xc2028_config cfg = { .i2c_adap = &dev->core->i2c_adap, .i2c_addr = addr, + .ctrl = &ctl, + .callback = cx88_tuner_callback, }; if (!dev->dvb.frontend) { @@ -469,6 +481,13 @@ static int attach_xc3028(u8 addr, struct cx8802_dev *dev) return -EINVAL; } + /* + * Some xc3028 devices may be hidden by an I2C gate. This is known + * to happen with some s5h1409-based devices. + * Now that I2C gate is open, sets up xc3028 configuration + */ + cx88_setup_xc3028(dev->core, &ctl); + fe = dvb_attach(xc2028_attach, dev->dvb.frontend, &cfg); if (!fe) { printk(KERN_ERR "%s/2: xc3028 attach failed\n", @@ -810,7 +829,7 @@ static int dvb_register(struct cx8802_dev *dev) return -EINVAL; break; case CX88_BOARD_GENIATECH_X8000_MT: - dev->ts_gen_cntrl = 0x00; + dev->ts_gen_cntrl = 0x00; dev->dvb.frontend = dvb_attach(zl10353_attach, &cx88_geniatech_x8000_mt, @@ -818,6 +837,13 @@ static int dvb_register(struct cx8802_dev *dev) if (attach_xc3028(0x61, dev) < 0) return -EINVAL; break; + case CX88_BOARD_KWORLD_ATSC_120: + dev->dvb.frontend = dvb_attach(s5h1409_attach, + &kworld_atsc_120_config, + &dev->core->i2c_adap); + if (attach_xc3028(0x61, dev) < 0) + return -EINVAL; + break; default: printk(KERN_ERR "%s/2: The frontend of your DVB/ATSC card isn't supported yet\n", dev->core->name); diff --git a/drivers/media/video/cx88/cx88.h b/drivers/media/video/cx88/cx88.h index c0f4912793e9..d17ca71c5d95 100644 --- a/drivers/media/video/cx88/cx88.h +++ b/drivers/media/video/cx88/cx88.h @@ -37,6 +37,7 @@ #include "btcx-risc.h" #include "cx88-reg.h" +#include "tuner-xc2028.h" #include #include @@ -219,6 +220,7 @@ extern struct sram_channel cx88_sram_channels[]; #define CX88_BOARD_DVICO_FUSIONHDTV_DVB_T_PRO 64 #define CX88_BOARD_DVICO_FUSIONHDTV_7_GOLD 65 #define CX88_BOARD_PROLINK_PV_8000GT 66 +#define CX88_BOARD_KWORLD_ATSC_120 67 enum cx88_itype { CX88_VMUX_COMPOSITE1 = 1, @@ -603,6 +605,7 @@ extern int cx88_tuner_callback(void *dev, int command, int arg); extern int cx88_get_resources(const struct cx88_core *core, struct pci_dev *pci); extern struct cx88_core *cx88_core_create(struct pci_dev *pci, int nr); +extern void cx88_setup_xc3028(struct cx88_core *core, struct xc2028_ctrl *ctl); /* ----------------------------------------------------------- */ /* cx88-tvaudio.c */ -- cgit v1.2.3 From fc9d8ed418619da915ad8a225fa974d813d0ca34 Mon Sep 17 00:00:00 2001 From: Matthias Schwarzott Date: Tue, 8 Apr 2008 21:45:08 -0300 Subject: V4L/DVB (7507): saa7134: add analog support for Avermedia A700 cards Add support for composite and s-video inputs on Avermedia DVB-S Pro and DVB-S Hybrid+FM cards (both labled A700) to the saa7134 driver. XC2028 support for Hybrid+FM is still missing. Signed-off-by: Matthias Schwarzott Reviewed-by: Hermann Pitton Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 2 + drivers/media/video/saa7134/saa7134-cards.c | 63 ++++++++++++++++++++++++++++- drivers/media/video/saa7134/saa7134.h | 2 + 3 files changed, 66 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index c1f9f138d1bb..fe925b335c94 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -138,3 +138,5 @@ 137 -> AVerMedia Hybrid TV/Radio (A16D) [1461:f936] 138 -> Avermedia M115 [1461:a836] 139 -> Compro VideoMate T750 [185b:c900] +140 -> Avermedia DVB-S Pro A700 [1461:a7a1] +141 -> Avermedia DVB-S Hybrid+FM A700 [1461:a7a2] diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index cfa13c2fb14f..82fe19c3b1db 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -4167,7 +4167,47 @@ struct saa7134_board saa7134_boards[] = { .name = name_radio, .amux = TV, } - } + }, + [SAA7134_BOARD_AVERMEDIA_A700_PRO] = { + /* Matthias Schwarzott */ + .name = "Avermedia DVB-S Pro A700", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_ABSENT, + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* no DVB support for now */ + /* .mpeg = SAA7134_MPEG_DVB, */ + .inputs = { { + .name = name_comp, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 6, + .amux = LINE1, + } }, + }, + [SAA7134_BOARD_AVERMEDIA_A700_HYBRID] = { + /* Matthias Schwarzott */ + .name = "Avermedia DVB-S Hybrid+FM A700", + .audio_clock = 0x00187de7, + .tuner_type = TUNER_ABSENT, /* TUNER_XC2028 */ + .radio_type = UNSET, + .tuner_addr = ADDR_UNSET, + .radio_addr = ADDR_UNSET, + /* no DVB support for now */ + /* .mpeg = SAA7134_MPEG_DVB, */ + .inputs = { { + .name = name_comp, + .vmux = 1, + .amux = LINE1, + }, { + .name = name_svideo, + .vmux = 6, + .amux = LINE1, + } }, + }, }; const unsigned int saa7134_bcount = ARRAY_SIZE(saa7134_boards); @@ -4399,6 +4439,18 @@ struct pci_device_id saa7134_pci_tbl[] = { .subdevice = 0xa70b, .driver_data = SAA7134_BOARD_MD2819, },{ + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa7a1, + .driver_data = SAA7134_BOARD_AVERMEDIA_A700_PRO, + }, { + .vendor = PCI_VENDOR_ID_PHILIPS, + .device = PCI_DEVICE_ID_PHILIPS_SAA7133, + .subvendor = 0x1461, /* Avermedia Technologies Inc */ + .subdevice = 0xa7a2, + .driver_data = SAA7134_BOARD_AVERMEDIA_A700_HYBRID, + }, { .vendor = PCI_VENDOR_ID_PHILIPS, .device = PCI_DEVICE_ID_PHILIPS_SAA7130, .subvendor = 0x1461, /* Avermedia Technologies Inc */ @@ -5462,6 +5514,15 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x8c040007, 0x8c040007); saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x0c0007cd, 0x0c0007cd); break; + case SAA7134_BOARD_AVERMEDIA_A700_PRO: + case SAA7134_BOARD_AVERMEDIA_A700_HYBRID: + /* write windows gpio values */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x80040100, 0x80040100); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x80040100, 0x00040100); + printk("%s: %s: hybrid analog/dvb card\n" + "%s: Sorry, only the analog inputs are supported for now.\n", + dev->name, card(dev).name, dev->name); + break; } return 0; } diff --git a/drivers/media/video/saa7134/saa7134.h b/drivers/media/video/saa7134/saa7134.h index 3394c47cea60..924ffd13637e 100644 --- a/drivers/media/video/saa7134/saa7134.h +++ b/drivers/media/video/saa7134/saa7134.h @@ -261,6 +261,8 @@ struct saa7134_format { #define SAA7134_BOARD_AVERMEDIA_A16D 137 #define SAA7134_BOARD_AVERMEDIA_M115 138 #define SAA7134_BOARD_VIDEOMATE_T750 139 +#define SAA7134_BOARD_AVERMEDIA_A700_PRO 140 +#define SAA7134_BOARD_AVERMEDIA_A700_HYBRID 141 #define SAA7134_MAXBOARDS 8 -- cgit v1.2.3 From c32d4d7510ae4da4e83bbd6e6471b04e9c9108ea Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 1 Apr 2008 01:27:41 -0300 Subject: V4L/DVB (7623): Scripts to maintain the CARDLIST file Scripts to maintain the CARDLIST file. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.au0828 | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 Documentation/video4linux/CARDLIST.au0828 (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.au0828 b/Documentation/video4linux/CARDLIST.au0828 new file mode 100644 index 000000000000..aaae360312e4 --- /dev/null +++ b/Documentation/video4linux/CARDLIST.au0828 @@ -0,0 +1,4 @@ + 0 -> Unknown board (au0828) + 1 -> Hauppauge HVR950Q (au0828) [2040:7200] + 2 -> Hauppauge HVR850 (au0828) [2040:7240] + 3 -> DViCO FusionHDTV USB (au0828) [0fe9:d620] -- cgit v1.2.3 From b3ea01668907bdb32b0c690d28f9f2b1298bd258 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 19 Apr 2008 01:14:19 -0300 Subject: V4L/DVB (7645): Add support for the Hauppauge HVR-1200 This adds support for DVB-T mode only, analog mode is not supported. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/Kconfig | 2 ++ drivers/media/video/cx23885/cx23885-cards.c | 22 ++++++++++++++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 26 ++++++++++++++++++++++++++ drivers/media/video/cx23885/cx23885-i2c.c | 1 + drivers/media/video/cx23885/cx23885.h | 1 + 6 files changed, 53 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 0924e6e142c4..3e9e999e5895 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -5,3 +5,4 @@ 4 -> DViCO FusionHDTV5 Express [18ac:d500] 5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797] 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717] + 7 -> Hauppauge WinTV-HVR1200 [0070:71d1] diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig index 1fd326fe4113..ca5fbce3a909 100644 --- a/drivers/media/video/cx23885/Kconfig +++ b/drivers/media/video/cx23885/Kconfig @@ -8,6 +8,7 @@ config VIDEO_CX23885 select VIDEO_TVEEPROM select VIDEO_IR select VIDEOBUF_DVB + select VIDEO_CX25840 select DVB_TUNER_MT2131 if !DVB_FE_CUSTOMISE select DVB_S5H1409 if !DVB_FE_CUSTOMISE select DVB_LGDT330X if !DVB_FE_CUSTOMISE @@ -16,6 +17,7 @@ config VIDEO_CX23885 select TUNER_TDA8290 if !DVB_FE_CUSTOMIZE select DVB_TDA18271 if !DVB_FE_CUSTOMIZE select DVB_TUNER_XC5000 if !DVB_FE_CUSTOMIZE + select DVB_TDA10048 if !DVB_FE_CUSTOMIZE ---help--- This is a video4linux driver for Conexant 23885 based TV cards. diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 77cd452e6e5b..8cb32f307a5d 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -130,6 +130,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1500", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1200] = { + .name = "Hauppauge WinTV-HVR1200", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -181,6 +185,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x7717, .card = CX23885_BOARD_HAUPPAUGE_HVR1500, + }, { + .subvendor = 0x0070, + .subdevice = 0x71d1, + .card = CX23885_BOARD_HAUPPAUGE_HVR1200, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -314,6 +322,17 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) cx_set(GP0_IO, 0x00040004); mdelay(20); break; + case CX23885_BOARD_HAUPPAUGE_HVR1200: + /* GPIO-0 tda10048 demodulator reset */ + /* GPIO-2 tda18271 tuner reset */ + + /* Put the parts into reset and back */ + cx_set(GP0_IO, 0x00050000); + mdelay(20); + cx_clear(GP0_IO, 0x00000005); + mdelay(20); + cx_set(GP0_IO, 0x00050005); + break; } } @@ -324,6 +343,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1800: + case CX23885_BOARD_HAUPPAUGE_HVR1200: /* FIXME: Implement me */ break; } @@ -353,6 +373,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) break; case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: + case CX23885_BOARD_HAUPPAUGE_HVR1200: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -369,6 +390,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: + case CX23885_BOARD_HAUPPAUGE_HVR1200: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 1a720abbd066..18cd90c9c0f3 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -36,6 +36,7 @@ #include "tda18271.h" #include "lgdt330x.h" #include "xc5000.h" +#include "tda10048.h" #include "dvb-pll.h" #include "tuner-xc2028.h" #include "tuner-xc2028-types.h" @@ -107,6 +108,13 @@ static struct s5h1409_config hauppauge_generic_config = { .mpeg_timing = S5H1409_MPEGTIMING_CONTINOUS_NONINVERTING_CLOCK, }; +static struct tda10048_config hauppauge_hvr1200_config = { + .demod_address = 0x10 >> 1, + .output_mode = TDA10048_SERIAL_OUTPUT, + .fwbulkwritelen = TDA10048_BULKWRITE_200, + .inversion = TDA10048_INVERSION_ON +}; + static struct s5h1409_config hauppauge_ezqam_config = { .demod_address = 0x32 >> 1, .output_mode = S5H1409_SERIAL_OUTPUT, @@ -178,6 +186,10 @@ static struct tda18271_config hauppauge_tda18271_config = { .gate = TDA18271_GATE_ANALOG, }; +static struct tda18271_config hauppauge_hvr1200_tuner_config = { + .gate = TDA18271_GATE_ANALOG, +}; + static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) { struct cx23885_tsport *port = ptr; @@ -317,6 +329,20 @@ static int dvb_register(struct cx23885_tsport *port) fe->ops.tuner_ops.set_config(fe, &ctl); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1200: + i2c_bus = &dev->i2c_bus[0]; + port->dvb.frontend = dvb_attach(tda10048_attach, + &hauppauge_hvr1200_config, + &i2c_bus->i2c_adap); + if (port->dvb.frontend != NULL) { + dvb_attach(tda829x_attach, port->dvb.frontend, + &dev->i2c_bus[1].i2c_adap, 0x42, + &tda829x_no_probe); + dvb_attach(tda18271_attach, port->dvb.frontend, + 0x60, &dev->i2c_bus[1].i2c_adap, + &hauppauge_hvr1200_tuner_config); + } + break; default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->name); diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 8773a1fd97cb..85f9d5ef17d0 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -353,6 +353,7 @@ static struct i2c_client cx23885_i2c_client_template = { }; static char *i2c_devs[128] = { + [0x10 >> 1] = "tda10048", [ 0x1c >> 1 ] = "lgdt3303", [ 0x86 >> 1 ] = "tda9887", [ 0x32 >> 1 ] = "cx24227", diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 7cb2179f2622..5bbfe6f50769 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -59,6 +59,7 @@ #define CX23885_BOARD_DVICO_FUSIONHDTV_5_EXP 4 #define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5 #define CX23885_BOARD_HAUPPAUGE_HVR1500 6 +#define CX23885_BOARD_HAUPPAUGE_HVR1200 7 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- cgit v1.2.3 From a780a31cee55e01e7b479244e7907ba842c120a0 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Sat, 19 Apr 2008 01:25:52 -0300 Subject: V4L/DVB (7647): Add support for the Hauppauge HVR-1700 digital mode This adds support for DVB-T mode only, analog is not supported. Signed-off-by: Steven Toth Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 34 +++++++++++++++++++++++++++++ drivers/media/video/cx23885/cx23885-dvb.c | 1 + drivers/media/video/cx23885/cx23885.h | 1 + 4 files changed, 37 insertions(+) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index 3e9e999e5895..b057a3c9f8ff 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -6,3 +6,4 @@ 5 -> Hauppauge WinTV-HVR1500Q [0070:7790,0070:7797] 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717] 7 -> Hauppauge WinTV-HVR1200 [0070:71d1] + 8 -> Hauppauge WinTV-HVR1700 [0070:8101] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 8cb32f307a5d..84636ffc64dc 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -134,6 +134,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1200", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1700] = { + .name = "Hauppauge WinTV-HVR1700", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -189,6 +193,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x71d1, .card = CX23885_BOARD_HAUPPAUGE_HVR1200, + }, { + .subvendor = 0x0070, + .subdevice = 0x8101, + .card = CX23885_BOARD_HAUPPAUGE_HVR1700, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -243,6 +251,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */ case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ + case 81519: + /* WinTV-HVR1700 (PCIe, Retail, No IR, half height, + * DVB-T and MPEG2 HW Encoder */ break; default: printk("%s: warning: unknown hauppauge model #%d\n", dev->name, tv.model); @@ -326,6 +337,27 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* GPIO-0 tda10048 demodulator reset */ /* GPIO-2 tda18271 tuner reset */ + /* Put the parts into reset and back */ + cx_set(GP0_IO, 0x00050000); + mdelay(20); + cx_clear(GP0_IO, 0x00000005); + mdelay(20); + cx_set(GP0_IO, 0x00050005); + break; + case CX23885_BOARD_HAUPPAUGE_HVR1700: + /* GPIO-0 TDA10048 demodulator reset */ + /* GPIO-2 TDA8295A Reset */ + /* GPIO-3-10 cx23417 data0-7 */ + /* GPIO-11-14 cx23417 addr0-3 */ + /* GPIO-15-18 cx23417 READY, CS, RD, WR */ + + /* The following GPIO's are on the interna AVCore (cx25840) */ + /* GPIO-19 IR_RX */ + /* GPIO-20 IR_TX 416/DVBT Select */ + /* GPIO-21 IIS DAT */ + /* GPIO-22 IIS WCLK */ + /* GPIO-23 IIS BCLK */ + /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); @@ -374,6 +406,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: + case CX23885_BOARD_HAUPPAUGE_HVR1700: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0xc0); break; @@ -391,6 +424,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: + case CX23885_BOARD_HAUPPAUGE_HVR1700: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 18cd90c9c0f3..a1086c8b66ee 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -330,6 +330,7 @@ static int dvb_register(struct cx23885_tsport *port) } break; case CX23885_BOARD_HAUPPAUGE_HVR1200: + case CX23885_BOARD_HAUPPAUGE_HVR1700: i2c_bus = &dev->i2c_bus[0]; port->dvb.frontend = dvb_attach(tda10048_attach, &hauppauge_hvr1200_config, diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index 5bbfe6f50769..c5496e08c949 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -60,6 +60,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1500Q 5 #define CX23885_BOARD_HAUPPAUGE_HVR1500 6 #define CX23885_BOARD_HAUPPAUGE_HVR1200 7 +#define CX23885_BOARD_HAUPPAUGE_HVR1700 8 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- cgit v1.2.3 From 33e5316113b1a472f54579f014739e4a4a53d704 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 21 Apr 2008 06:58:48 -0300 Subject: V4L/DVB (7651): tuner-xc2028: Several fixes to SCODE This patch fixes several issues on SCODE: 1) The extracting tool weren't generating the proper tags for SCODE. This has almost no effect, since those tags shouldn't be used; 2) DIBCOM52 were using a wrong IF. It should be 5200, instead of 5700; 3) seek_firmware were wanting an exact match for firmware type. This is wrong. As result, no SCODE firmware were loaded; 4) A few files were including the wrong file for seeking demod firmwares; 5) XC3028_FE_DEFAULT can be used, if user doesn't want to load a firmware. However, this weren't documentated. This feature require more testing. Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/extract_xc3028.pl | 46 ++++++++++++++--------------- drivers/media/dvb/dvb-usb/cxusb.c | 3 +- drivers/media/video/cx23885/cx23885-dvb.c | 3 +- drivers/media/video/cx88/cx88-dvb.c | 3 +- drivers/media/video/tuner-xc2028-types.h | 18 +++++++---- drivers/media/video/tuner-xc2028.c | 21 ++++++++----- drivers/media/video/tuner-xc2028.h | 4 +-- 7 files changed, 54 insertions(+), 44 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/extract_xc3028.pl b/Documentation/video4linux/extract_xc3028.pl index cced8ac5c543..2cb816047fc1 100644 --- a/Documentation/video4linux/extract_xc3028.pl +++ b/Documentation/video4linux/extract_xc3028.pl @@ -686,11 +686,11 @@ sub main_firmware($$$$) write_hunk(812664, 192); # - # Firmware 58, type: SCODE FW HAS IF (0x60000000), IF = 4.50 MHz id: NTSC/M Jp (0000000000002000), size: 192 + # Firmware 58, type: SCODE FW MTS LCD NOGD MONO IF HAS IF (0x6002b004), IF = 4.50 MHz id: NTSC PAL/M PAL/N (000000000000b700), size: 192 # - write_le32(0x60000000); # Type - write_le64(0x00000000, 0x00002000); # ID + write_le32(0x6002b004); # Type + write_le64(0x00000000, 0x0000b700); # ID write_le16(4500); # IF write_le32(192); # Size write_hunk(807672, 192); @@ -706,10 +706,10 @@ sub main_firmware($$$$) write_hunk(807864, 192); # - # Firmware 60, type: SCODE FW DTV78 ZARLINK456 HAS IF (0x62000100), IF = 4.76 MHz id: (0000000000000000), size: 192 + # Firmware 60, type: SCODE FW DTV6 QAM DTV7 DTV78 DTV8 ZARLINK456 HAS IF (0x620003e0), IF = 4.76 MHz id: (0000000000000000), size: 192 # - write_le32(0x62000100); # Type + write_le32(0x620003e0); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(4760); # IF write_le32(192); # Size @@ -726,30 +726,30 @@ sub main_firmware($$$$) write_hunk(811512, 192); # - # Firmware 62, type: SCODE FW DTV7 ZARLINK456 HAS IF (0x62000080), IF = 5.26 MHz id: (0000000000000000), size: 192 + # Firmware 62, type: SCODE FW HAS IF (0x60000000), IF = 5.26 MHz id: (0000000000000000), size: 192 # - write_le32(0x62000080); # Type + write_le32(0x60000000); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(5260); # IF write_le32(192); # Size write_hunk(810552, 192); # - # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192 + # Firmware 63, type: SCODE FW MONO HAS IF (0x60008000), IF = 5.32 MHz id: PAL/BG A2 NICAM (0000000f00000007), size: 192 # write_le32(0x60008000); # Type - write_le64(0x00000008, 0x00000007); # ID + write_le64(0x0000000f, 0x00000007); # ID write_le16(5320); # IF write_le32(192); # Size write_hunk(810744, 192); # - # Firmware 64, type: SCODE FW DTV8 CHINA HAS IF (0x64000200), IF = 5.40 MHz id: (0000000000000000), size: 192 + # Firmware 64, type: SCODE FW DTV7 DTV78 DTV8 DIBCOM52 CHINA HAS IF (0x65000380), IF = 5.40 MHz id: (0000000000000000), size: 192 # - write_le32(0x64000200); # Type + write_le32(0x65000380); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(5400); # IF write_le32(192); # Size @@ -766,50 +766,50 @@ sub main_firmware($$$$) write_hunk(809592, 192); # - # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2/B (0000000200000007), size: 192 + # Firmware 66, type: SCODE FW HAS IF (0x60000000), IF = 5.64 MHz id: PAL/BG A2 (0000000300000007), size: 192 # write_le32(0x60000000); # Type - write_le64(0x00000002, 0x00000007); # ID + write_le64(0x00000003, 0x00000007); # ID write_le16(5640); # IF write_le32(192); # Size write_hunk(808440, 192); # - # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM/B (0000000800000007), size: 192 + # Firmware 67, type: SCODE FW HAS IF (0x60000000), IF = 5.74 MHz id: PAL/BG NICAM (0000000c00000007), size: 192 # write_le32(0x60000000); # Type - write_le64(0x00000008, 0x00000007); # ID + write_le64(0x0000000c, 0x00000007); # ID write_le16(5740); # IF write_le32(192); # Size write_hunk(808632, 192); # - # Firmware 68, type: SCODE FW DTV7 DIBCOM52 HAS IF (0x61000080), IF = 5.90 MHz id: (0000000000000000), size: 192 + # Firmware 68, type: SCODE FW HAS IF (0x60000000), IF = 5.90 MHz id: (0000000000000000), size: 192 # - write_le32(0x61000080); # Type + write_le32(0x60000000); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(5900); # IF write_le32(192); # Size write_hunk(810360, 192); # - # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/I (0000000000000010), size: 192 + # Firmware 69, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.00 MHz id: PAL/DK PAL/I SECAM/K3 SECAM/L SECAM/Lc NICAM (0000000c04c000f0), size: 192 # write_le32(0x60008000); # Type - write_le64(0x00000000, 0x00000010); # ID + write_le64(0x0000000c, 0x04c000f0); # ID write_le16(6000); # IF write_le32(192); # Size write_hunk(808824, 192); # - # Firmware 70, type: SCODE FW DTV6 QAM F6MHZ HAS IF (0x68000060), IF = 6.20 MHz id: (0000000000000000), size: 192 + # Firmware 70, type: SCODE FW DTV6 QAM ATSC LG60 F6MHZ HAS IF (0x68050060), IF = 6.20 MHz id: (0000000000000000), size: 192 # - write_le32(0x68000060); # Type + write_le32(0x68050060); # Type write_le64(0x00000000, 0x00000000); # ID write_le16(6200); # IF write_le32(192); # Size @@ -846,11 +846,11 @@ sub main_firmware($$$$) write_hunk(809208, 192); # - # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: SECAM/K3 (0000000004000000), size: 192 + # Firmware 74, type: SCODE FW MONO HAS IF (0x60008000), IF = 6.50 MHz id: PAL/DK SECAM/K3 SECAM/L NICAM (0000000c044000e0), size: 192 # write_le32(0x60008000); # Type - write_le64(0x00000000, 0x04000000); # ID + write_le64(0x0000000c, 0x044000e0); # ID write_le16(6500); # IF write_le32(192); # Size write_hunk(811128, 192); diff --git a/drivers/media/dvb/dvb-usb/cxusb.c b/drivers/media/dvb/dvb-usb/cxusb.c index c4b00660c65f..720fcd1c3c1d 100644 --- a/drivers/media/dvb/dvb-usb/cxusb.c +++ b/drivers/media/dvb/dvb-usb/cxusb.c @@ -33,7 +33,6 @@ #include "mt352_priv.h" #include "zl10353.h" #include "tuner-xc2028.h" -#include "tuner-xc2028-types.h" #include "tuner-simple.h" /* debug */ @@ -521,7 +520,7 @@ static int cxusb_dvico_xc3028_tuner_attach(struct dvb_usb_adapter *adap) static struct xc2028_ctrl ctl = { .fname = "xc3028-dvico-au-01.fw", .max_len = 64, - .scode_table = ZARLINK456, + .scode_table = XC3028_FE_ZARLINK456, }; fe = dvb_attach(xc2028_attach, adap->fe, &cfg); diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index a1086c8b66ee..1b9a85e43d44 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -39,7 +39,6 @@ #include "tda10048.h" #include "dvb-pll.h" #include "tuner-xc2028.h" -#include "tuner-xc2028-types.h" #include "tuner-simple.h" static unsigned int debug; @@ -320,7 +319,7 @@ static int dvb_register(struct cx23885_tsport *port) static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", .max_len = 64, - .scode_table = OREN538, + .scode_table = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, diff --git a/drivers/media/video/cx88/cx88-dvb.c b/drivers/media/video/cx88/cx88-dvb.c index fda7334d934b..f1251b844e08 100644 --- a/drivers/media/video/cx88/cx88-dvb.c +++ b/drivers/media/video/cx88/cx88-dvb.c @@ -45,7 +45,6 @@ #include "nxt200x.h" #include "cx24123.h" #include "isl6421.h" -#include "tuner-xc2028-types.h" #include "tuner-simple.h" #include "tda9887.h" @@ -813,7 +812,7 @@ static int dvb_register(struct cx8802_dev *dev) static struct xc2028_ctrl ctl = { .fname = "xc3028-v27.fw", .max_len = 64, - .scode_table = OREN538, + .scode_table = XC3028_FE_OREN538, }; fe = dvb_attach(xc2028_attach, diff --git a/drivers/media/video/tuner-xc2028-types.h b/drivers/media/video/tuner-xc2028-types.h index d0057fbf0ec7..17633c316c28 100644 --- a/drivers/media/video/tuner-xc2028-types.h +++ b/drivers/media/video/tuner-xc2028-types.h @@ -1,6 +1,9 @@ /* tuner-xc2028_types * - * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * This file includes internal tipes to be used inside tuner-xc2028. + * Shouldn't be included outside tuner-xc2028 + * + * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) * This code is placed under the terms of the GNU General Public License v2 */ @@ -85,11 +88,16 @@ /* This flag identifies that the scode table has a new format */ #define HAS_IF (1 << 30) -#define SCODE_TYPES (MTS|DTV6|QAM|DTV7|DTV78|DTV8|LCD|NOGD|MONO|ATSC|IF| \ - LG60|ATI638|OREN538|OREN36|TOYOTA388|TOYOTA794| \ - DIBCOM52|ZARLINK456|CHINA|F6MHZ|SCODE) +#define SCODE_TYPES SCODE + -/* Newer types to be moved to videodev2.h */ +/* Newer types not defined on videodev2.h. + The original idea were to move all those types to videodev2.h, but + it seemed overkill, since, with the exception of SECAM/K3, the other + types seem to be autodetected. + It is not clear where secam/k3 is used, nor we have a feedback of this + working or being autodetected by the standard secam firmware. + */ #define V4L2_STD_SECAM_K3 (0x04000000) diff --git a/drivers/media/video/tuner-xc2028.c b/drivers/media/video/tuner-xc2028.c index 9dd688ec3cff..0e580bcd0e09 100644 --- a/drivers/media/video/tuner-xc2028.c +++ b/drivers/media/video/tuner-xc2028.c @@ -1,6 +1,6 @@ /* tuner-xc2028 * - * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) * * Copyright (c) 2007 Michel Ludwig (michel.ludwig@gmail.com) * - frontend interface @@ -404,7 +404,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, { struct xc2028_data *priv = fe->tuner_priv; int i, best_i = -1, best_nr_matches = 0; - unsigned int ign_firm_type_mask = 0; + unsigned int type_mask = 0; tuner_dbg("%s called, want type=", __func__); if (debug) { @@ -421,18 +421,23 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, *id = V4L2_STD_PAL; if (type & BASE) - type &= BASE_TYPES; + type_mask = BASE_TYPES; else if (type & SCODE) { type &= SCODE_TYPES; - ign_firm_type_mask = HAS_IF; + type_mask = SCODE_TYPES & ~HAS_IF; } else if (type & DTV_TYPES) - type &= DTV_TYPES; + type_mask = DTV_TYPES; else if (type & STD_SPECIFIC_TYPES) - type &= STD_SPECIFIC_TYPES; + type_mask = STD_SPECIFIC_TYPES; + + type &= type_mask; + + if (!type & SCODE) + type_mask = ~0; /* Seek for exact match */ for (i = 0; i < priv->firm_size; i++) { - if ((type == (priv->firm[i].type & ~ign_firm_type_mask)) && + if ((type == (priv->firm[i].type & type_mask)) && (*id == priv->firm[i].id)) goto found; } @@ -442,7 +447,7 @@ static int seek_firmware(struct dvb_frontend *fe, unsigned int type, v4l2_std_id match_mask; int nr_matches; - if (type != (priv->firm[i].type & ~ign_firm_type_mask)) + if (type != (priv->firm[i].type & type_mask)) continue; match_mask = *id & priv->firm[i].id; diff --git a/drivers/media/video/tuner-xc2028.h b/drivers/media/video/tuner-xc2028.h index 612e490634d0..fc2f132a5541 100644 --- a/drivers/media/video/tuner-xc2028.h +++ b/drivers/media/video/tuner-xc2028.h @@ -1,6 +1,6 @@ /* tuner-xc2028 * - * Copyright (c) 2007 Mauro Carvalho Chehab (mchehab@infradead.org) + * Copyright (c) 2007-2008 Mauro Carvalho Chehab (mchehab@infradead.org) * This code is placed under the terms of the GNU General Public License v2 */ @@ -12,7 +12,7 @@ #define XC2028_DEFAULT_FIRMWARE "xc3028-v27.fw" /* Dmoduler IF (kHz) */ -#define XC3028_FE_DEFAULT 0 +#define XC3028_FE_DEFAULT 0 /* Don't load SCODE */ #define XC3028_FE_LG60 6000 #define XC3028_FE_ATI638 6380 #define XC3028_FE_OREN538 5380 -- cgit v1.2.3 From 6676237398d0c2e61e5a3a27e0951f60d6ef6fe3 Mon Sep 17 00:00:00 2001 From: Steven Toth Date: Tue, 22 Apr 2008 15:38:26 -0300 Subject: V4L/DVB (7673): cx23885: Add support for the Hauppauge HVR1400 DVB-T mode is now supported using the DiBcom dib7000p demodulator and the Xceive xc3028L silicon tuner. Analog mode is not supported. Signed-off-by: Steven Toth Reviewed-by: Patrick Boettcher Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.cx23885 | 1 + drivers/media/video/cx23885/cx23885-cards.c | 26 +++++++ drivers/media/video/cx23885/cx23885-dvb.c | 113 ++++++++++++++++++++++++++++ drivers/media/video/cx23885/cx23885-i2c.c | 4 +- drivers/media/video/cx23885/cx23885.h | 1 + 5 files changed, 144 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.cx23885 b/Documentation/video4linux/CARDLIST.cx23885 index b057a3c9f8ff..929b90c8387f 100644 --- a/Documentation/video4linux/CARDLIST.cx23885 +++ b/Documentation/video4linux/CARDLIST.cx23885 @@ -7,3 +7,4 @@ 6 -> Hauppauge WinTV-HVR1500 [0070:7710,0070:7717] 7 -> Hauppauge WinTV-HVR1200 [0070:71d1] 8 -> Hauppauge WinTV-HVR1700 [0070:8101] + 9 -> Hauppauge WinTV-HVR1400 [0070:8010] diff --git a/drivers/media/video/cx23885/cx23885-cards.c b/drivers/media/video/cx23885/cx23885-cards.c index 859510f7469c..0f4b325f2d89 100644 --- a/drivers/media/video/cx23885/cx23885-cards.c +++ b/drivers/media/video/cx23885/cx23885-cards.c @@ -138,6 +138,10 @@ struct cx23885_board cx23885_boards[] = { .name = "Hauppauge WinTV-HVR1700", .portc = CX23885_MPEG_DVB, }, + [CX23885_BOARD_HAUPPAUGE_HVR1400] = { + .name = "Hauppauge WinTV-HVR1400", + .portc = CX23885_MPEG_DVB, + }, }; const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards); @@ -197,6 +201,10 @@ struct cx23885_subid cx23885_subids[] = { .subvendor = 0x0070, .subdevice = 0x8101, .card = CX23885_BOARD_HAUPPAUGE_HVR1700, + }, { + .subvendor = 0x0070, + .subdevice = 0x8010, + .card = CX23885_BOARD_HAUPPAUGE_HVR1400, }, }; const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids); @@ -251,6 +259,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data) case 79561: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ case 79571: /* WinTV-HVR1250 (PCIe, OEM, No IR, full height, ATSC and Basic analog */ case 79671: /* WinTV-HVR1250 (PCIe, OEM, No IR, half height, ATSC and Basic analog */ + case 80019: + /* WinTV-HVR1400 (Express Card, Retail, IR, + * DVB-T and Basic analog */ case 81519: /* WinTV-HVR1700 (PCIe, Retail, No IR, half height, * DVB-T and MPEG2 HW Encoder */ @@ -358,6 +369,18 @@ void cx23885_gpio_setup(struct cx23885_dev *dev) /* GPIO-22 IIS WCLK */ /* GPIO-23 IIS BCLK */ + /* Put the parts into reset and back */ + cx_set(GP0_IO, 0x00050000); + mdelay(20); + cx_clear(GP0_IO, 0x00000005); + mdelay(20); + cx_set(GP0_IO, 0x00050005); + break; + case CX23885_BOARD_HAUPPAUGE_HVR1400: + /* GPIO-0 Dibcom7000p demodulator reset */ + /* GPIO-2 xc3028L tuner reset */ + /* GPIO-13 LED */ + /* Put the parts into reset and back */ cx_set(GP0_IO, 0x00050000); mdelay(20); @@ -376,6 +399,7 @@ int cx23885_ir_init(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1500Q: case CX23885_BOARD_HAUPPAUGE_HVR1800: case CX23885_BOARD_HAUPPAUGE_HVR1200: + case CX23885_BOARD_HAUPPAUGE_HVR1400: /* FIXME: Implement me */ break; } @@ -400,6 +424,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1250: case CX23885_BOARD_HAUPPAUGE_HVR1500: case CX23885_BOARD_HAUPPAUGE_HVR1500Q: + case CX23885_BOARD_HAUPPAUGE_HVR1400: if (dev->i2c_bus[0].i2c_rc == 0) hauppauge_eeprom(dev, eeprom+0x80); break; @@ -425,6 +450,7 @@ void cx23885_card_setup(struct cx23885_dev *dev) case CX23885_BOARD_HAUPPAUGE_HVR1800lp: case CX23885_BOARD_HAUPPAUGE_HVR1200: case CX23885_BOARD_HAUPPAUGE_HVR1700: + case CX23885_BOARD_HAUPPAUGE_HVR1400: default: ts2->gen_ctrl_val = 0xc; /* Serial bus + punctured clock */ ts2->ts_clk_en_val = 0x1; /* Enable TS_CLK */ diff --git a/drivers/media/video/cx23885/cx23885-dvb.c b/drivers/media/video/cx23885/cx23885-dvb.c index 1b9a85e43d44..870d6e197d65 100644 --- a/drivers/media/video/cx23885/cx23885-dvb.c +++ b/drivers/media/video/cx23885/cx23885-dvb.c @@ -40,6 +40,8 @@ #include "dvb-pll.h" #include "tuner-xc2028.h" #include "tuner-simple.h" +#include "dib7000p.h" +#include "dibx000_common.h" static unsigned int debug; @@ -189,6 +191,92 @@ static struct tda18271_config hauppauge_hvr1200_tuner_config = { .gate = TDA18271_GATE_ANALOG, }; +struct dibx000_agc_config xc3028_agc_config = { + BAND_VHF | BAND_UHF, /* band_caps */ + + /* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=0, + * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, + * P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, + * P_agc_nb_est=2, P_agc_write=0 + */ + (0 << 15) | (0 << 14) | (0 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | + (3 << 5) | (0 << 4) | (2 << 1) | (0 << 0), /* setup */ + + 712, /* inv_gain */ + 21, /* time_stabiliz */ + + 0, /* alpha_level */ + 118, /* thlock */ + + 0, /* wbd_inv */ + 2867, /* wbd_ref */ + 0, /* wbd_sel */ + 2, /* wbd_alpha */ + + 0, /* agc1_max */ + 0, /* agc1_min */ + 39718, /* agc2_max */ + 9930, /* agc2_min */ + 0, /* agc1_pt1 */ + 0, /* agc1_pt2 */ + 0, /* agc1_pt3 */ + 0, /* agc1_slope1 */ + 0, /* agc1_slope2 */ + 0, /* agc2_pt1 */ + 128, /* agc2_pt2 */ + 29, /* agc2_slope1 */ + 29, /* agc2_slope2 */ + + 17, /* alpha_mant */ + 27, /* alpha_exp */ + 23, /* beta_mant */ + 51, /* beta_exp */ + + 1, /* perform_agc_softsplit */ +}; + +/* PLL Configuration for COFDM BW_MHz = 8.000000 + * With external clock = 30.000000 */ +struct dibx000_bandwidth_config xc3028_bw_config = { + 60000, /* internal */ + 30000, /* sampling */ + 1, /* pll_cfg: prediv */ + 8, /* pll_cfg: ratio */ + 3, /* pll_cfg: range */ + 1, /* pll_cfg: reset */ + 0, /* pll_cfg: bypass */ + 0, /* misc: refdiv */ + 0, /* misc: bypclk_div */ + 1, /* misc: IO_CLK_en_core */ + 1, /* misc: ADClkSrc */ + 0, /* misc: modulo */ + (3 << 14) | (1 << 12) | (524 << 0), /* sad_cfg: refsel, sel, freq_15k */ + (1 << 25) | 5816102, /* ifreq = 5.200000 MHz */ + 20452225, /* timf */ + 30000000 /* xtal_hz */ +}; + +static struct dib7000p_config hauppauge_hvr1400_dib7000_config = { + .output_mpeg2_in_188_bytes = 1, + .hostbus_diversity = 1, + .tuner_is_baseband = 0, + .update_lna = NULL, + + .agc_config_count = 1, + .agc = &xc3028_agc_config, + .bw = &xc3028_bw_config, + + .gpio_dir = DIB7000P_GPIO_DEFAULT_DIRECTIONS, + .gpio_val = DIB7000P_GPIO_DEFAULT_VALUES, + .gpio_pwm_pos = DIB7000P_GPIO_DEFAULT_PWM_POS, + + .pwm_freq_div = 0, + .agc_control = NULL, + .spur_protect = 0, + + .output_mode = OUTMODE_MPEG2_SERIAL, +}; + static int cx23885_hvr1500_xc3028_callback(void *ptr, int command, int arg) { struct cx23885_tsport *port = ptr; @@ -343,6 +431,31 @@ static int dvb_register(struct cx23885_tsport *port) &hauppauge_hvr1200_tuner_config); } break; + case CX23885_BOARD_HAUPPAUGE_HVR1400: + i2c_bus = &dev->i2c_bus[0]; + port->dvb.frontend = dvb_attach(dib7000p_attach, + &i2c_bus->i2c_adap, + 0x12, &hauppauge_hvr1400_dib7000_config); + if (port->dvb.frontend != NULL) { + struct dvb_frontend *fe; + struct xc2028_config cfg = { + .i2c_adap = &dev->i2c_bus[1].i2c_adap, + .i2c_addr = 0x64, + .callback = cx23885_hvr1500_xc3028_callback, + }; + static struct xc2028_ctrl ctl = { + .fname = "xc3028L-v36.fw", + .max_len = 64, + .demod = 5000, + .d2633 = 1 + }; + + fe = dvb_attach(xc2028_attach, + port->dvb.frontend, &cfg); + if (fe != NULL && fe->ops.tuner_ops.set_config != NULL) + fe->ops.tuner_ops.set_config(fe, &ctl); + } + break; default: printk("%s: The frontend of your DVB/ATSC card isn't supported yet\n", dev->name); diff --git a/drivers/media/video/cx23885/cx23885-i2c.c b/drivers/media/video/cx23885/cx23885-i2c.c index 85f9d5ef17d0..3928945df5f5 100644 --- a/drivers/media/video/cx23885/cx23885-i2c.c +++ b/drivers/media/video/cx23885/cx23885-i2c.c @@ -354,6 +354,7 @@ static struct i2c_client cx23885_i2c_client_template = { static char *i2c_devs[128] = { [0x10 >> 1] = "tda10048", + [0x12 >> 1] = "dib7000pc", [ 0x1c >> 1 ] = "lgdt3303", [ 0x86 >> 1 ] = "tda9887", [ 0x32 >> 1 ] = "cx24227", @@ -361,7 +362,8 @@ static char *i2c_devs[128] = { [ 0x84 >> 1 ] = "tda8295", [ 0xa0 >> 1 ] = "eeprom", [ 0xc0 >> 1 ] = "tuner/mt2131/tda8275", - [ 0xc2 >> 1 ] = "tuner/mt2131/tda8275/xc5000", + [0xc2 >> 1] = "tuner/mt2131/tda8275/xc5000/xc3028", + [0xc8 >> 1] = "tuner/xc3028L", }; static void do_i2c_scan(char *name, struct i2c_client *c) diff --git a/drivers/media/video/cx23885/cx23885.h b/drivers/media/video/cx23885/cx23885.h index c5496e08c949..3705e6019ce9 100644 --- a/drivers/media/video/cx23885/cx23885.h +++ b/drivers/media/video/cx23885/cx23885.h @@ -61,6 +61,7 @@ #define CX23885_BOARD_HAUPPAUGE_HVR1500 6 #define CX23885_BOARD_HAUPPAUGE_HVR1200 7 #define CX23885_BOARD_HAUPPAUGE_HVR1700 8 +#define CX23885_BOARD_HAUPPAUGE_HVR1400 9 /* Currently unsupported by the driver: PAL/H, NTSC/Kr, SECAM B/G/H/LC */ #define CX23885_NORMS (\ -- cgit v1.2.3 From b34dddbe4b88bf59e7607d1fc504eee43570c6a4 Mon Sep 17 00:00:00 2001 From: Dmitry Belimov Date: Wed, 23 Apr 2008 14:09:08 -0300 Subject: V4L/DVB (7677): saa7134: Add/fix Beholder entries Beholder TV/FM tuners: Changes: Add support Beholder Columbus PCMCIA card. Add key map for remote control of Beholder Columbus PCMCIA card. Fix gpiomask for all Beholder tuners. Signed-off-by: Beholder Intl. Ltd. Dmitry Belimov Signed-off-by: Mauro Carvalho Chehab --- Documentation/video4linux/CARDLIST.saa7134 | 4 +- drivers/media/common/ir-keymaps.c | 70 +++++++++++++++++++++++++ drivers/media/video/saa7134/saa7134-cards.c | 80 ++++++++++++++++++++++++++--- drivers/media/video/saa7134/saa7134-input.c | 13 ++++- include/media/ir-common.h | 1 + 5 files changed, 157 insertions(+), 11 deletions(-) (limited to 'Documentation') diff --git a/Documentation/video4linux/CARDLIST.saa7134 b/Documentation/video4linux/CARDLIST.saa7134 index fe925b335c94..44d84dd15ad6 100644 --- a/Documentation/video4linux/CARDLIST.saa7134 +++ b/Documentation/video4linux/CARDLIST.saa7134 @@ -25,8 +25,8 @@ 24 -> KNC One TV-Station DVR [1894:a006] 25 -> ASUS TV-FM 7133 [1043:4843] 26 -> Pinnacle PCTV Stereo (saa7134) [11bd:002b] - 27 -> Manli MuchTV M-TV002/Behold TV 403 FM - 28 -> Manli MuchTV M-TV001/Behold TV 401 + 27 -> Manli MuchTV M-TV002 + 28 -> Manli MuchTV M-TV001 29 -> Nagase Sangyo TransGear 3000TV [1461:050c] 30 -> Elitegroup ECS TVP3XP FM1216 Tuner Card(PAL-BG,FM) [1019:4cb4] 31 -> Elitegroup ECS TVP3XP FM1236 Tuner Card (NTSC,FM) [1019:4cb5] diff --git a/drivers/media/common/ir-keymaps.c b/drivers/media/common/ir-keymaps.c index 65f810cde605..a3485817e46c 100644 --- a/drivers/media/common/ir-keymaps.c +++ b/drivers/media/common/ir-keymaps.c @@ -2043,6 +2043,76 @@ IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE] = { EXPORT_SYMBOL_GPL(ir_codes_behold); +/* Beholder Intl. Ltd. 2008 + * Dmitry Belimov d.belimov@google.com + * Keytable is used by BeholdTV Columbus + * The "ascii-art picture" below (in comments, first row + * is the keycode in hex, and subsequent row(s) shows + * the button labels (several variants when appropriate) + * helps to descide which keycodes to assign to the buttons. + */ +IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE] = { + + /* 0x13 0x11 0x1C 0x12 * + * Mute Source TV/FM Power * + * */ + + [0x13] = KEY_MUTE, + [0x11] = KEY_PROPS, + [0x1C] = KEY_TUNER, /* KEY_TV/KEY_RADIO */ + [0x12] = KEY_POWER, + + /* 0x01 0x02 0x03 0x0D * + * 1 2 3 Stereo * + * * + * 0x04 0x05 0x06 0x19 * + * 4 5 6 Snapshot * + * * + * 0x07 0x08 0x09 0x10 * + * 7 8 9 Zoom * + * */ + [0x01] = KEY_1, + [0x02] = KEY_2, + [0x03] = KEY_3, + [0x0D] = KEY_SETUP, /* Setup key */ + [0x04] = KEY_4, + [0x05] = KEY_5, + [0x06] = KEY_6, + [0x19] = KEY_BOOKMARKS, /* Snapshot key */ + [0x07] = KEY_7, + [0x08] = KEY_8, + [0x09] = KEY_9, + [0x10] = KEY_ZOOM, + + /* 0x0A 0x00 0x0B 0x0C * + * RECALL 0 ChannelUp VolumeUp * + * */ + [0x0A] = KEY_AGAIN, + [0x00] = KEY_0, + [0x0B] = KEY_CHANNELUP, + [0x0C] = KEY_VOLUMEUP, + + /* 0x1B 0x1D 0x15 0x18 * + * Timeshift Record ChannelDown VolumeDown * + * */ + + [0x1B] = KEY_REWIND, + [0x1D] = KEY_RECORD, + [0x15] = KEY_CHANNELDOWN, + [0x18] = KEY_VOLUMEDOWN, + + /* 0x0E 0x1E 0x0F 0x1A * + * Stop Pause Previouse Next * + * */ + + [0x0E] = KEY_STOP, + [0x1E] = KEY_PAUSE, + [0x0F] = KEY_PREVIOUS, + [0x1A] = KEY_NEXT, + +}; +EXPORT_SYMBOL_GPL(ir_codes_behold_columbus); + /* * Remote control for the Genius TVGO A11MCE * Adrian Pardini diff --git a/drivers/media/video/saa7134/saa7134-cards.c b/drivers/media/video/saa7134/saa7134-cards.c index 82fe19c3b1db..98375955a84b 100644 --- a/drivers/media/video/saa7134/saa7134-cards.c +++ b/drivers/media/video/saa7134/saa7134-cards.c @@ -30,6 +30,7 @@ #include "tuner-xc2028.h" #include #include +#include "tea5767.h" /* commly used strings */ static char name_mute[] = "mute"; @@ -1049,7 +1050,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_MANLI_MTV002] = { /* Ognjen Nastic */ - .name = "Manli MuchTV M-TV002/Behold TV 403 FM", + .name = "Manli MuchTV M-TV002", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_PAL, .radio_type = UNSET, @@ -1076,7 +1077,7 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_MANLI_MTV001] = { /* Ognjen Nastic UNTESTED */ - .name = "Manli MuchTV M-TV001/Behold TV 401", + .name = "Manli MuchTV M-TV001", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_PAL, .radio_type = UNSET, @@ -2198,6 +2199,8 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_BEHOLD_409FM] = { /* , Sergey */ + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 409 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -2205,6 +2208,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3576,12 +3580,15 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_401] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 401", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3602,12 +3609,15 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_403] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 403", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3624,12 +3634,15 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_403FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 403 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FQ1216ME, .radio_type = UNSET, .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3650,6 +3663,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_405] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 405", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3657,6 +3672,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3674,6 +3690,8 @@ struct saa7134_board saa7134_boards[] = { }, [SAA7134_BOARD_BEHOLD_405FM] = { /* Sergey */ + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 405 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3681,6 +3699,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3701,6 +3720,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_407] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 407", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3708,7 +3729,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0xc0c000, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3728,6 +3749,8 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_407FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 407 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3735,7 +3758,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, - .gpiomask = 0xc0c000, + .gpiomask = 0x00008000, .inputs = {{ .name = name_svideo, .vmux = 8, @@ -3760,6 +3783,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_409] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 409", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3767,6 +3792,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3783,6 +3809,8 @@ struct saa7134_board saa7134_boards[] = { }}, }, [SAA7134_BOARD_BEHOLD_505FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 505 FM/RDS", .audio_clock = 0x00200000, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3790,6 +3818,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3814,6 +3843,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_507_9FM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV 507 FM/RDS / BeholdTV 509 FM", .audio_clock = 0x00187de7, .tuner_type = TUNER_PHILIPS_FM1216ME_MK3, @@ -3821,6 +3852,7 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x00008000, .inputs = {{ .name = name_tv, .vmux = 3, @@ -3841,6 +3873,8 @@ struct saa7134_board saa7134_boards[] = { }, }, [SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM] = { + /* Beholder Intl. Ltd. 2008 */ + /*Dmitry Belimov */ .name = "Beholder BeholdTV Columbus TVFM", .audio_clock = 0x00187de7, .tuner_type = TUNER_ALPS_TSBE5_PAL, @@ -3848,23 +3882,28 @@ struct saa7134_board saa7134_boards[] = { .tuner_addr = ADDR_UNSET, .radio_addr = ADDR_UNSET, .tda9887_conf = TDA9887_PRESENT, + .gpiomask = 0x000A8004, .inputs = {{ .name = name_tv, .vmux = 3, .amux = TV, .tv = 1, - },{ + .gpio = 0x000A8004, + }, { .name = name_comp1, .vmux = 1, .amux = LINE1, - },{ + .gpio = 0x000A8000, + }, { .name = name_svideo, .vmux = 8, .amux = LINE1, - }}, + .gpio = 0x000A8000, + } }, .radio = { .name = name_radio, .amux = LINE2, + .gpio = 0x000A8000, }, }, [SAA7134_BOARD_BEHOLD_607_9FM] = { @@ -5471,7 +5510,6 @@ int saa7134_board_init1(struct saa7134_dev *dev) case SAA7134_BOARD_AVERMEDIA_CARDBUS: case SAA7134_BOARD_AVERMEDIA_CARDBUS_506: case SAA7134_BOARD_AVERMEDIA_M115: - case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: case SAA7134_BOARD_AVERMEDIA_A16D: /* power-down tuner chip */ saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0xffffffff, 0); @@ -5482,6 +5520,18 @@ int saa7134_board_init1(struct saa7134_dev *dev) saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0xffffffff, 0xffffffff); msleep(10); break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + /* power-down tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0); + msleep(10); + /* power-up tuner chip */ + saa_andorl(SAA7134_GPIO_GPMODE0 >> 2, 0x000A8004, 0x000A8004); + saa_andorl(SAA7134_GPIO_GPSTATUS0 >> 2, 0x000A8004, 0x000A8004); + msleep(10); + /* remote via GPIO */ + dev->has_remote = SAA7134_REMOTE_GPIO; + break; case SAA7134_BOARD_RTD_VFG7350: /* @@ -5770,6 +5820,20 @@ int saa7134_board_init2(struct saa7134_dev *dev) break; } break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + { + struct v4l2_priv_tun_config tea5767_cfg; + struct tea5767_ctrl ctl; + + dev->i2c_client.addr = 0xC0; + /* set TEA5767(analog FM) defines */ + memset(&ctl, 0, sizeof(ctl)); + ctl.xtal_freq = TEA5767_HIGH_LO_13MHz; + tea5767_cfg.tuner = TUNER_TEA5767; + tea5767_cfg.priv = &ctl; + saa7134_i2c_call_clients(dev, TUNER_SET_CONFIG, &tea5767_cfg); + } + break; } if (dev->tuner_type == TUNER_XC2028) { diff --git a/drivers/media/video/saa7134/saa7134-input.c b/drivers/media/video/saa7134/saa7134-input.c index 65f8e594d6fb..767ff30832f2 100644 --- a/drivers/media/video/saa7134/saa7134-input.c +++ b/drivers/media/video/saa7134/saa7134-input.c @@ -331,6 +331,11 @@ int saa7134_input_init1(struct saa7134_dev *dev) break; case SAA7134_BOARD_MANLI_MTV001: case SAA7134_BOARD_MANLI_MTV002: + ir_codes = ir_codes_manli; + mask_keycode = 0x001f00; + mask_keyup = 0x004000; + polling = 50; /* ms */ + break; case SAA7134_BOARD_BEHOLD_409FM: case SAA7134_BOARD_BEHOLD_401: case SAA7134_BOARD_BEHOLD_403: @@ -343,7 +348,13 @@ int saa7134_input_init1(struct saa7134_dev *dev) case SAA7134_BOARD_BEHOLD_505FM: case SAA7134_BOARD_BEHOLD_507_9FM: ir_codes = ir_codes_manli; - mask_keycode = 0x001f00; + mask_keycode = 0x003f00; + mask_keyup = 0x004000; + polling = 50; /* ms */ + break; + case SAA7134_BOARD_BEHOLD_COLUMBUS_TVFM: + ir_codes = ir_codes_behold_columbus; + mask_keycode = 0x003f00; mask_keyup = 0x004000; polling = 50; // ms break; diff --git a/include/media/ir-common.h b/include/media/ir-common.h index 75a3482866fe..bfee8be5d63f 100644 --- a/include/media/ir-common.h +++ b/include/media/ir-common.h @@ -142,6 +142,7 @@ extern IR_KEYTAB_TYPE ir_codes_encore_enltv[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_tt_1500[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_fusionhdtv_mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_behold[IR_KEYTAB_SIZE]; +extern IR_KEYTAB_TYPE ir_codes_behold_columbus[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_pinnacle_pctv_hd[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_genius_tvgo_a11mce[IR_KEYTAB_SIZE]; extern IR_KEYTAB_TYPE ir_codes_powercolor_real_angel[IR_KEYTAB_SIZE]; -- cgit v1.2.3 From b912b5e2cfb35c02c9c79d3f6e31753f3be4dd83 Mon Sep 17 00:00:00 2001 From: John Linn Date: Thu, 3 Apr 2008 10:22:19 +1100 Subject: [POWERPC] Xilinx: of_serial support for Xilinx uart 16550. The Xilinx 16550 uart core is not a standard 16550 because it uses word-based addressing rather than byte-based addressing. With additional properties it is compatible with the open firmware 'ns16550' compatible binding. This code updates the of_serial driver to handle the reg-offset and reg-shift properties to enable this core to be used. Signed-off-by: John Linn Acked-by: Arnd Bergmann Signed-off-by: Josh Boyer --- Documentation/powerpc/booting-without-of.txt | 11 +++++++++++ drivers/serial/of_serial.c | 14 +++++++++++++- 2 files changed, 24 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/powerpc/booting-without-of.txt b/Documentation/powerpc/booting-without-of.txt index 4cc780024e6c..cf89e8cfd5bf 100644 --- a/Documentation/powerpc/booting-without-of.txt +++ b/Documentation/powerpc/booting-without-of.txt @@ -2601,6 +2601,17 @@ platforms are moved over to use the flattened-device-tree model. differ between different families. May be 'virtex2p', 'virtex4', or 'virtex5'. + vi) Xilinx Uart 16550 + + Xilinx UART 16550 devices are very similar to the NS16550 but with + different register spacing and an offset from the base address. + + Requred properties: + - clock-frequency : Frequency of the clock input + - reg-offset : A value of 3 is required + - reg-shift : A value of 2 is required + + p) Freescale Synchronous Serial Interface The SSI is a serial device that communicates with audio codecs. It can diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c index 8aacfb78deab..25029c7570b6 100644 --- a/drivers/serial/of_serial.c +++ b/drivers/serial/of_serial.c @@ -31,7 +31,8 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, struct resource resource; struct device_node *np = ofdev->node; const unsigned int *clk, *spd; - int ret; + const u32 *prop; + int ret, prop_size; memset(port, 0, sizeof *port); spd = of_get_property(np, "current-speed", NULL); @@ -49,6 +50,17 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev, spin_lock_init(&port->lock); port->mapbase = resource.start; + + /* Check for shifted address mapping */ + prop = of_get_property(np, "reg-offset", &prop_size); + if (prop && (prop_size == sizeof(u32))) + port->mapbase += *prop; + + /* Check for registers offset within the devices address range */ + prop = of_get_property(np, "reg-shift", &prop_size); + if (prop && (prop_size == sizeof(u32))) + port->regshift = *prop; + port->irq = irq_of_parse_and_map(np, 0); port->iotype = UPIO_MEM; port->type = type; -- cgit v1.2.3 From 22c36d18c668db1a8d92a9a47e09857974f6a49b Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Wed, 23 Apr 2008 10:34:52 -0600 Subject: Document SEQ_SKIP 2.6.26 adds a SEQ_SKIP return value for the seq_file show() function; update the documentation to match. Signed-off-by: Jonathan Corbet --- Documentation/filesystems/seq_file.txt | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/seq_file.txt b/Documentation/filesystems/seq_file.txt index 7fb8e6dc62bf..0ab92c260894 100644 --- a/Documentation/filesystems/seq_file.txt +++ b/Documentation/filesystems/seq_file.txt @@ -122,8 +122,7 @@ stop() is the place to free it. } Finally, the show() function should format the object currently pointed to -by the iterator for output. It should return zero, or an error code if -something goes wrong. The example module's show() function is: +by the iterator for output. The example module's show() function is: static int ct_seq_show(struct seq_file *s, void *v) { @@ -132,6 +131,12 @@ something goes wrong. The example module's show() function is: return 0; } +If all is well, the show() function should return zero. A negative error +code in the usual manner indicates that something went wrong; it will be +passed back to user space. This function can also return SEQ_SKIP, which +causes the current item to be skipped; if the show() function has already +generated output before returning SEQ_SKIP, that output will be dropped. + We will look at seq_printf() in a moment. But first, the definition of the seq_file iterator is finished by creating a seq_operations structure with the four functions we have just defined: -- cgit v1.2.3 From 0013b23d66a2768f5babbb0ea9f03ab067a990d8 Mon Sep 17 00:00:00 2001 From: Németh Márton Date: Sun, 9 Mar 2008 20:54:37 +0000 Subject: leds: disable triggers on brightness set MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Disable any active triggers when the brightness attribute is set to zero. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Márton Németh Signed-off-by: Richard Purdie --- Documentation/leds-class.txt | 12 +++++++++--- drivers/leds/led-class.c | 3 +++ drivers/leds/led-triggers.c | 12 +++++++++--- drivers/leds/leds.h | 7 +++++++ drivers/leds/ledtrig-timer.c | 23 +++++++++++++++++++---- 5 files changed, 47 insertions(+), 10 deletions(-) (limited to 'Documentation') diff --git a/Documentation/leds-class.txt b/Documentation/leds-class.txt index 56757c751d6f..18860ad9935a 100644 --- a/Documentation/leds-class.txt +++ b/Documentation/leds-class.txt @@ -19,6 +19,12 @@ optimises away. Complex triggers whilst available to all LEDs have LED specific parameters and work on a per LED basis. The timer trigger is an example. +The timer trigger will periodically change the LED brightness between +LED_OFF and the current brightness setting. The "on" and "off" time can +be specified via /sys/class/leds//delay_{on,off} in milliseconds. +You can change the brightness value of a LED independently of the timer +trigger. However, if you set the brightness value to LED_OFF it will +also disable the timer trigger. You can change triggers in a similar manner to the way an IO scheduler is chosen (via /sys/class/leds//trigger). Trigger specific @@ -63,9 +69,9 @@ value if it is called with *delay_on==0 && *delay_off==0 parameters. In this case the driver should give back the chosen value through delay_on and delay_off parameters to the leds subsystem. -Any call to the brightness_set() callback function should cancel the -previously programmed hardware blinking function so setting the brightness -to 0 can also cancel the blinking of the LED. +Setting the brightness to zero with brightness_set() callback function +should completely turn off the LED and cancel the previously programmed +hardware blinking function, if any. Known Issues diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c index 63aad90247c4..a8dd59ebedf8 100644 --- a/drivers/leds/led-class.c +++ b/drivers/leds/led-class.c @@ -51,6 +51,9 @@ static ssize_t led_brightness_store(struct device *dev, if (count == size) { ret = count; + + if (state == LED_OFF) + led_trigger_remove(led_cdev); led_set_brightness(led_cdev, state); } diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c index 13c9026d68af..21dd96909444 100644 --- a/drivers/leds/led-triggers.c +++ b/drivers/leds/led-triggers.c @@ -45,9 +45,7 @@ ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, trigger_name[len - 1] = '\0'; if (!strcmp(trigger_name, "none")) { - down_write(&led_cdev->trigger_lock); - led_trigger_set(led_cdev, NULL); - up_write(&led_cdev->trigger_lock); + led_trigger_remove(led_cdev); return count; } @@ -139,6 +137,13 @@ void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) led_cdev->trigger = trigger; } +void led_trigger_remove(struct led_classdev *led_cdev) +{ + down_write(&led_cdev->trigger_lock); + led_trigger_set(led_cdev, NULL); + up_write(&led_cdev->trigger_lock); +} + void led_trigger_set_default(struct led_classdev *led_cdev) { struct led_trigger *trig; @@ -231,6 +236,7 @@ void led_trigger_unregister_simple(struct led_trigger *trigger) /* Used by LED Class */ EXPORT_SYMBOL_GPL(led_trigger_set); +EXPORT_SYMBOL_GPL(led_trigger_remove); EXPORT_SYMBOL_GPL(led_trigger_set_default); EXPORT_SYMBOL_GPL(led_trigger_show); EXPORT_SYMBOL_GPL(led_trigger_store); diff --git a/drivers/leds/leds.h b/drivers/leds/leds.h index 12b6fe93b135..0214799639f7 100644 --- a/drivers/leds/leds.h +++ b/drivers/leds/leds.h @@ -27,6 +27,11 @@ static inline void led_set_brightness(struct led_classdev *led_cdev, led_cdev->brightness_set(led_cdev, value); } +static inline int led_get_brightness(struct led_classdev *led_cdev) +{ + return led_cdev->brightness; +} + extern struct rw_semaphore leds_list_lock; extern struct list_head leds_list; @@ -34,9 +39,11 @@ extern struct list_head leds_list; void led_trigger_set_default(struct led_classdev *led_cdev); void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger); +void led_trigger_remove(struct led_classdev *led_cdev); #else #define led_trigger_set_default(x) do {} while(0) #define led_trigger_set(x, y) do {} while(0) +#define led_trigger_remove(x) do {} while(0) #endif ssize_t led_trigger_store(struct device *dev, struct device_attribute *attr, diff --git a/drivers/leds/ledtrig-timer.c b/drivers/leds/ledtrig-timer.c index 82c55d6e4902..706297765d93 100644 --- a/drivers/leds/ledtrig-timer.c +++ b/drivers/leds/ledtrig-timer.c @@ -25,6 +25,9 @@ #include "leds.h" struct timer_trig_data { + int brightness_on; /* LED brightness during "on" period. + * (LED_OFF < brightness_on <= LED_FULL) + */ unsigned long delay_on; /* milliseconds on */ unsigned long delay_off; /* milliseconds off */ struct timer_list timer; @@ -34,17 +37,26 @@ static void led_timer_function(unsigned long data) { struct led_classdev *led_cdev = (struct led_classdev *) data; struct timer_trig_data *timer_data = led_cdev->trigger_data; - unsigned long brightness = LED_OFF; - unsigned long delay = timer_data->delay_off; + unsigned long brightness; + unsigned long delay; if (!timer_data->delay_on || !timer_data->delay_off) { led_set_brightness(led_cdev, LED_OFF); return; } - if (!led_cdev->brightness) { - brightness = LED_FULL; + brightness = led_get_brightness(led_cdev); + if (!brightness) { + /* Time to switch the LED on. */ + brightness = timer_data->brightness_on; delay = timer_data->delay_on; + } else { + /* Store the current brightness value to be able + * to restore it when the delay_off period is over. + */ + timer_data->brightness_on = brightness; + brightness = LED_OFF; + delay = timer_data->delay_off; } led_set_brightness(led_cdev, brightness); @@ -156,6 +168,9 @@ static void timer_trig_activate(struct led_classdev *led_cdev) if (!timer_data) return; + timer_data->brightness_on = led_get_brightness(led_cdev); + if (timer_data->brightness_on == LED_OFF) + timer_data->brightness_on = LED_FULL; led_cdev->trigger_data = timer_data; init_timer(&timer_data->timer); -- cgit v1.2.3 From feccc30d90155bcbc937f87643182a43d25873eb Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 3 Mar 2008 15:15:59 -0500 Subject: USB: remove CONFIG_USB_PERSIST setting This patch (as1047) removes the USB_PERSIST Kconfig option, enabling it permanently. It also prevents the power/persist attribute from being created for hub devices; there's no point in having it since USB-PERSIST is always turned on for hubs. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/persist.txt | 35 +++++++++++++++++++---------------- drivers/usb/core/Kconfig | 25 ------------------------- drivers/usb/core/hub.c | 27 ++++++++++----------------- drivers/usb/core/quirks.c | 12 ++++++++++++ drivers/usb/core/sysfs.c | 22 ++++++++++------------ drivers/usb/host/ehci-hub.c | 11 +---------- include/linux/usb.h | 2 +- 7 files changed, 53 insertions(+), 81 deletions(-) (limited to 'Documentation') diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt index df54d645cbb5..bea58dbd30fe 100644 --- a/Documentation/usb/persist.txt +++ b/Documentation/usb/persist.txt @@ -2,7 +2,7 @@ Alan Stern - September 2, 2006 (Updated May 29, 2007) + September 2, 2006 (Updated February 25, 2008) What is the problem? @@ -65,9 +65,10 @@ much better.) What is the solution? -Setting CONFIG_USB_PERSIST will cause the kernel to work around these -issues. It enables a mode in which the core USB device data -structures are allowed to persist across a power-session disruption. +The kernel includes a feature called USB-persist. It tries to work +around these issues by allowing the core USB device data structures to +persist across a power-session disruption. + It works like this. If the kernel sees that a USB host controller is not in the expected state during resume (i.e., if the controller was reset or otherwise had lost power) then it applies a persistence check @@ -80,28 +81,30 @@ re-enumeration shows that the device now attached to that port has the same descriptors as before, including the Vendor and Product IDs, then the kernel continues to use the same device structure. In effect, the kernel treats the device as though it had merely been reset instead of -unplugged. +unplugged. The same thing happens if the host controller is in the +expected state but a USB device was unplugged and then replugged. If no device is now attached to the port, or if the descriptors are different from what the kernel remembers, then the treatment is what you would expect. The kernel destroys the old device structure and behaves as though the old device had been unplugged and a new device -plugged in, just as it would without the CONFIG_USB_PERSIST option. +plugged in. The end result is that the USB device remains available and usable. Filesystem mounts and memory mappings are unaffected, and the world is now a good and happy place. -Note that even when CONFIG_USB_PERSIST is set, the "persist" feature -will be applied only to those devices for which it is enabled. You -can enable the feature by doing (as root): +Note that the "USB-persist" feature will be applied only to those +devices for which it is enabled. You can enable the feature by doing +(as root): echo 1 >/sys/bus/usb/devices/.../power/persist where the "..." should be filled in the with the device's ID. Disable the feature by writing 0 instead of 1. For hubs the feature is -automatically and permanently enabled, so you only have to worry about -setting it for devices where it really matters. +automatically and permanently enabled and the power/persist file +doesn't even exist, so you only have to worry about setting it for +devices where it really matters. Is this the best solution? @@ -112,19 +115,19 @@ centralized Logical Volume Manager. Such a solution would allow you to plug in a USB flash device, create a persistent volume associated with it, unplug the flash device, plug it back in later, and still have the same persistent volume associated with the device. As such -it would be more far-reaching than CONFIG_USB_PERSIST. +it would be more far-reaching than USB-persist. On the other hand, writing a persistent volume manager would be a big job and using it would require significant input from the user. This solution is much quicker and easier -- and it exists now, a giant point in its favor! -Furthermore, the USB_PERSIST option applies to _all_ USB devices, not +Furthermore, the USB-persist feature applies to _all_ USB devices, not just mass-storage devices. It might turn out to be equally useful for other device types, such as network interfaces. - WARNING: Using CONFIG_USB_PERSIST can be dangerous!! + WARNING: USB-persist can be dangerous!! When recovering an interrupted power session the kernel does its best to make sure the USB device hasn't been changed; that is, the same @@ -152,5 +155,5 @@ but yourself. YOU HAVE BEEN WARNED! USE AT YOUR OWN RISK! That having been said, most of the time there shouldn't be any trouble -at all. The "persist" feature can be extremely useful. Make the most -of it. +at all. The USB-persist feature can be extremely useful. Make the +most of it. diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig index a2b0aa48b8ea..c15621d64579 100644 --- a/drivers/usb/core/Kconfig +++ b/drivers/usb/core/Kconfig @@ -102,31 +102,6 @@ config USB_SUSPEND If you are unsure about this, say N here. -config USB_PERSIST - bool "USB device persistence during system suspend (DANGEROUS)" - depends on USB && PM && EXPERIMENTAL - default n - help - - If you say Y here and enable the "power/persist" attribute - for a USB device, the device's data structures will remain - persistent across system suspend, even if the USB bus loses - power. (This includes hibernation, also known as swsusp or - suspend-to-disk.) The devices will reappear as if by magic - when the system wakes up, with no need to unmount USB - filesystems, rmmod host-controller drivers, or do anything - else. - - WARNING: This option can be dangerous! - - If a USB device is replaced by another of the same type while - the system is asleep, there's a good chance the kernel won't - detect the change. Likewise if the media in a USB storage - device is replaced. When this happens it's almost certain to - cause data corruption and maybe even crash your system. - - If you are unsure, say N here. - config USB_OTG bool depends on USB && EXPERIMENTAL diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index df68e2562582..6dc589955d75 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -30,12 +30,6 @@ #include "hcd.h" #include "hub.h" -#ifdef CONFIG_USB_PERSIST -#define USB_PERSIST 1 -#else -#define USB_PERSIST 0 -#endif - /* if we are in debug mode, always announce new devices */ #ifdef DEBUG #ifndef CONFIG_USB_ANNOUNCE_NEW_DEVICES @@ -695,7 +689,7 @@ static void hub_restart(struct usb_hub *hub, int type) * turn off the various status changes to prevent * khubd from disconnecting it later. */ - if (USB_PERSIST && udev->persist_enabled && status == 0 && + if (udev->persist_enabled && status == 0 && !(portstatus & USB_PORT_STAT_ENABLE)) { if (portchange & USB_PORT_STAT_C_ENABLE) clear_port_feature(hub->hdev, port1, @@ -1923,9 +1917,8 @@ static int finish_port_resume(struct usb_device *udev) * the host and the device is the same as it was when the device * suspended. * - * If CONFIG_USB_PERSIST and @udev->reset_resume are both set then this - * routine won't check that the port is still enabled. Furthermore, - * if @udev->reset_resume is set then finish_port_resume() above will + * If @udev->reset_resume is set then this routine won't check that the + * port is still enabled. Furthermore, finish_port_resume() above will * reset @udev. The end result is that a broken power session can be * recovered and @udev will appear to persist across a loss of VBUS power. * @@ -1937,8 +1930,8 @@ static int finish_port_resume(struct usb_device *udev) * to it will be lost. Using the USB_PERSIST facility, the device can be * made to appear as if it had not disconnected. * - * This facility is inherently dangerous. Although usb_reset_device() - * makes every effort to insure that the same device is present after the + * This facility can be dangerous. Although usb_reset_device() makes + * every effort to insure that the same device is present after the * reset as before, it cannot provide a 100% guarantee. Furthermore it's * quite possible for a device to remain unaltered but its media to be * changed. If the user replaces a flash memory card while the system is @@ -1983,7 +1976,7 @@ int usb_port_resume(struct usb_device *udev) status = hub_port_status(hub, port1, &portstatus, &portchange); SuspendCleared: - if (USB_PERSIST && udev->reset_resume) + if (udev->reset_resume) want_flags = USB_PORT_STAT_POWER | USB_PORT_STAT_CONNECTION; else @@ -2113,10 +2106,10 @@ static int hub_reset_resume(struct usb_interface *intf) * * The USB host controller driver calls this function when its root hub * is resumed and Vbus power has been interrupted or the controller - * has been reset. The routine marks @rhdev as having lost power. When - * the hub driver is resumed it will take notice; if CONFIG_USB_PERSIST - * is enabled then it will carry out power-session recovery, otherwise - * it will disconnect all the child devices. + * has been reset. The routine marks @rhdev as having lost power. + * When the hub driver is resumed it will take notice and carry out + * power-session recovery for all the "USB-PERSIST"-enabled child devices; + * the others will be disconnected. */ void usb_root_hub_lost_power(struct usb_device *rhdev) { diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index dfc5418ea10c..f384edf35b44 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -97,4 +97,16 @@ void usb_detect_quirks(struct usb_device *udev) if (udev->descriptor.bDeviceClass != USB_CLASS_HUB) udev->autosuspend_disabled = 1; #endif + +#ifdef CONFIG_PM + /* Hubs are automatically enabled for USB-PERSIST */ + if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) + udev->persist_enabled = 1; +#else + /* In the absense of PM, we can safely enable USB-PERSIST + * for all devices. It will affect things like hub resets + * and EMF-related port disables. + */ + udev->persist_enabled = 1; +#endif /* CONFIG_PM */ } diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c index a37ccbd1e007..5b20a60de8ba 100644 --- a/drivers/usb/core/sysfs.c +++ b/drivers/usb/core/sysfs.c @@ -180,11 +180,9 @@ show_urbnum(struct device *dev, struct device_attribute *attr, char *buf) static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL); -#if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND) -static const char power_group[] = "power"; -#endif +#ifdef CONFIG_PM -#ifdef CONFIG_USB_PERSIST +static const char power_group[] = "power"; static ssize_t show_persist(struct device *dev, struct device_attribute *attr, char *buf) @@ -222,12 +220,13 @@ static int add_persist_attributes(struct device *dev) if (is_usb_device(dev)) { struct usb_device *udev = to_usb_device(dev); - /* Hubs are automatically enabled for USB_PERSIST */ - if (udev->descriptor.bDeviceClass == USB_CLASS_HUB) - udev->persist_enabled = 1; - rc = sysfs_add_file_to_group(&dev->kobj, - &dev_attr_persist.attr, - power_group); + /* Hubs are automatically enabled for USB_PERSIST, + * no point in creating the attribute file. + */ + if (udev->descriptor.bDeviceClass != USB_CLASS_HUB) + rc = sysfs_add_file_to_group(&dev->kobj, + &dev_attr_persist.attr, + power_group); } return rc; } @@ -238,13 +237,12 @@ static void remove_persist_attributes(struct device *dev) &dev_attr_persist.attr, power_group); } - #else #define add_persist_attributes(dev) 0 #define remove_persist_attributes(dev) do {} while (0) -#endif /* CONFIG_USB_PERSIST */ +#endif /* CONFIG_PM */ #ifdef CONFIG_USB_SUSPEND diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 8d513a15d0cd..fea9e47192db 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c @@ -28,7 +28,7 @@ /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_PERSIST +#ifdef CONFIG_PM static int ehci_hub_control( struct usb_hcd *hcd, @@ -104,15 +104,6 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) ehci->owned_ports = 0; } -#else /* CONFIG_USB_PERSIST */ - -static inline void ehci_handover_companion_ports(struct ehci_hcd *ehci) -{ } - -#endif - -#ifdef CONFIG_PM - static int ehci_bus_suspend (struct usb_hcd *hcd) { struct ehci_hcd *ehci = hcd_to_ehci (hcd); diff --git a/include/linux/usb.h b/include/linux/usb.h index 583e0481dfa0..7e31cacfe69c 100644 --- a/include/linux/usb.h +++ b/include/linux/usb.h @@ -387,6 +387,7 @@ struct usb_device { unsigned can_submit:1; /* URBs may be submitted */ unsigned discon_suspended:1; /* Disconnected while suspended */ + unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */ unsigned have_langid:1; /* whether string_langid is valid */ unsigned authorized:1; /* Policy has said we can use it */ unsigned wusb:1; /* Device is Wireless USB */ @@ -433,7 +434,6 @@ struct usb_device { unsigned auto_pm:1; /* autosuspend/resume in progress */ unsigned do_remote_wakeup:1; /* remote wakeup should be enabled */ unsigned reset_resume:1; /* needs reset instead of resume */ - unsigned persist_enabled:1; /* USB_PERSIST enabled for this dev */ unsigned autosuspend_disabled:1; /* autosuspend and autoresume */ unsigned autoresume_disabled:1; /* disabled by the user */ unsigned skip_sys_resume:1; /* skip the next system resume */ -- cgit v1.2.3 From eb764c4be1e5db3ee34df5745e98cf2f148c7320 Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Mon, 3 Mar 2008 15:16:04 -0500 Subject: USB: check serial-number string after device reset This patch (as1048) extends the descriptor checking after a device is reset. Now the SerialNumber string descriptor is compared to its old value, in addition to the device and configuration descriptors. As a consequence, the kmalloc() call in usb_string() is now on the error-handling pathway for usb-storage. Hence its allocation type is changed to GFO_NOIO. Signed-off-by: Alan Stern Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/persist.txt | 8 +++--- drivers/usb/core/hub.c | 65 +++++++++++++++++++++++++++++++++---------- drivers/usb/core/message.c | 2 +- 3 files changed, 55 insertions(+), 20 deletions(-) (limited to 'Documentation') diff --git a/Documentation/usb/persist.txt b/Documentation/usb/persist.txt index bea58dbd30fe..d56cb1a11550 100644 --- a/Documentation/usb/persist.txt +++ b/Documentation/usb/persist.txt @@ -136,10 +136,10 @@ aren't guaranteed to be 100% accurate. If you replace one USB device with another of the same type (same manufacturer, same IDs, and so on) there's an excellent chance the -kernel won't detect the change. Serial numbers and other strings are -not compared. In many cases it wouldn't help if they were, because -manufacturers frequently omit serial numbers entirely in their -devices. +kernel won't detect the change. The serial number string and other +descriptors are compared with the kernel's stored values, but this +might not help since manufacturers frequently omit serial numbers +entirely in their devices. Furthermore it's quite possible to leave a USB device exactly the same while changing its media. If you replace the flash memory card in a diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index 6dc589955d75..9fc5179dfc60 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -3010,16 +3010,36 @@ void usb_hub_cleanup(void) usb_deregister(&hub_driver); } /* usb_hub_cleanup() */ -static int config_descriptors_changed(struct usb_device *udev) -{ - unsigned index; - unsigned len = 0; - struct usb_config_descriptor *buf; +static int descriptors_changed(struct usb_device *udev, + struct usb_device_descriptor *old_device_descriptor) +{ + int changed = 0; + unsigned index; + unsigned serial_len = 0; + unsigned len; + unsigned old_length; + int length; + char *buf; + + if (memcmp(&udev->descriptor, old_device_descriptor, + sizeof(*old_device_descriptor)) != 0) + return 1; + + /* Since the idVendor, idProduct, and bcdDevice values in the + * device descriptor haven't changed, we will assume the + * Manufacturer and Product strings haven't changed either. + * But the SerialNumber string could be different (e.g., a + * different flash card of the same brand). + */ + if (udev->serial) + serial_len = strlen(udev->serial) + 1; + len = serial_len; for (index = 0; index < udev->descriptor.bNumConfigurations; index++) { - if (len < le16_to_cpu(udev->config[index].desc.wTotalLength)) - len = le16_to_cpu(udev->config[index].desc.wTotalLength); + old_length = le16_to_cpu(udev->config[index].desc.wTotalLength); + len = max(len, old_length); } + buf = kmalloc(len, GFP_NOIO); if (buf == NULL) { dev_err(&udev->dev, "no mem to re-read configs after reset\n"); @@ -3027,25 +3047,41 @@ static int config_descriptors_changed(struct usb_device *udev) return 1; } for (index = 0; index < udev->descriptor.bNumConfigurations; index++) { - int length; - int old_length = le16_to_cpu(udev->config[index].desc.wTotalLength); - + old_length = le16_to_cpu(udev->config[index].desc.wTotalLength); length = usb_get_descriptor(udev, USB_DT_CONFIG, index, buf, old_length); - if (length < old_length) { + if (length != old_length) { dev_dbg(&udev->dev, "config index %d, error %d\n", index, length); + changed = 1; break; } if (memcmp (buf, udev->rawdescriptors[index], old_length) != 0) { dev_dbg(&udev->dev, "config index %d changed (#%d)\n", - index, buf->bConfigurationValue); + index, + ((struct usb_config_descriptor *) buf)-> + bConfigurationValue); + changed = 1; break; } } + + if (!changed && serial_len) { + length = usb_string(udev, udev->descriptor.iSerialNumber, + buf, serial_len); + if (length + 1 != serial_len) { + dev_dbg(&udev->dev, "serial string error %d\n", + length); + changed = 1; + } else if (memcmp(buf, udev->serial, length) != 0) { + dev_dbg(&udev->dev, "serial string changed\n"); + changed = 1; + } + } + kfree(buf); - return index != udev->descriptor.bNumConfigurations; + return changed; } /** @@ -3118,8 +3154,7 @@ int usb_reset_device(struct usb_device *udev) goto re_enumerate; /* Device might have changed firmware (DFU or similar) */ - if (memcmp(&udev->descriptor, &descriptor, sizeof descriptor) - || config_descriptors_changed (udev)) { + if (descriptors_changed(udev, &descriptor)) { dev_info(&udev->dev, "device firmware changed\n"); udev->descriptor = descriptor; /* for disconnect() calls */ goto re_enumerate; diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c index c311f67b7f08..a3695b5115ff 100644 --- a/drivers/usb/core/message.c +++ b/drivers/usb/core/message.c @@ -784,7 +784,7 @@ int usb_string(struct usb_device *dev, int index, char *buf, size_t size) if (size <= 0 || !buf || !index) return -EINVAL; buf[0] = 0; - tbuf = kmalloc(256, GFP_KERNEL); + tbuf = kmalloc(256, GFP_NOIO); if (!tbuf) return -ENOMEM; -- cgit v1.2.3 From e04d80b03d2a116ddd6eb9140c8c83760c315b94 Mon Sep 17 00:00:00 2001 From: Matti Linnanvuori Date: Sun, 23 Mar 2008 04:08:01 -0700 Subject: USB: serial: Remove obsolete contact addresses Remove obsolete contact addresses. Signed-off-by: Matti Linnanvuori Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/usb-serial.txt | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/usb/usb-serial.txt b/Documentation/usb/usb-serial.txt index 8b077e43eee7..ff2c1ff57ba2 100644 --- a/Documentation/usb/usb-serial.txt +++ b/Documentation/usb/usb-serial.txt @@ -192,12 +192,9 @@ Keyspan USA-series Serial Adapters FTDI Single Port Serial Driver - This is a single port DB-25 serial adapter. More information about this - device and the Linux driver can be found at: - http://reality.sgi.com/bryder_wellington/ftdi_sio/ + This is a single port DB-25 serial adapter. - For any questions or problems with this driver, please contact Bill Ryder - at bryder@sgi.com + For any questions or problems with this driver, please contact Bill Ryder. ZyXEL omni.net lcd plus ISDN TA -- cgit v1.2.3 From e6a79f1f07fc88a2efd6d0e8f0ccf591cb93cd34 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 9 Apr 2008 15:37:34 +0200 Subject: USB: add Documentation about usb_anchor This adds documentation about the new usb anchor infrastructure. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/anchors.txt | 50 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 Documentation/usb/anchors.txt (limited to 'Documentation') diff --git a/Documentation/usb/anchors.txt b/Documentation/usb/anchors.txt new file mode 100644 index 000000000000..7304bcf5a306 --- /dev/null +++ b/Documentation/usb/anchors.txt @@ -0,0 +1,50 @@ +What is anchor? +=============== + +A USB driver needs to support some callbacks requiring +a driver to cease all IO to an interface. To do so, a +driver has to keep track of the URBs it has submitted +to know they've all completed or to call usb_kill_urb +for them. The anchor is a data structure takes care of +keeping track of URBs and provides methods to deal with +multiple URBs. + +Allocation and Initialisation +============================= + +There's no API to allocate an anchor. It is simply declared +as struct usb_anchor. init_usb_anchor() must be called to +initialise the data structure. + +Deallocation +============ + +Once it has no more URBs associated with it, the anchor can be +freed with normal memory management operations. + +Association and disassociation of URBs with anchors +=================================================== + +An association of URBs to an anchor is made by an explicit +call to usb_anchor_urb(). The association is maintained until +an URB is finished by (successfull) completion. Thus disassociation +is automatic. A function is provided to forcibly finish (kill) +all URBs associated with an anchor. +Furthermore, disassociation can be made with usb_unanchor_urb() + +Operations on multitudes of URBs +================================ + +usb_kill_anchored_urbs() +------------------------ + +This function kills all URBs associated with an anchor. The URBs +are called in the reverse temporal order they were submitted. +This way no data can be reordered. + +usb_wait_anchor_empty_timeout() +------------------------------- + +This function waits for all URBs associated with an anchor to finish +or a timeout, whichever comes first. Its return value will tell you +whether the timeout was reached. -- cgit v1.2.3 From 08177e12b7b4c3d59060f829e5c151d06f9a08d6 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Wed, 16 Apr 2008 15:46:37 +0200 Subject: USB: add documentation about callbacks Add Documentation about callbacks in USB. Signed-off-by: Oliver Neukum Signed-off-by: Greg Kroah-Hartman --- Documentation/usb/callbacks.txt | 132 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 Documentation/usb/callbacks.txt (limited to 'Documentation') diff --git a/Documentation/usb/callbacks.txt b/Documentation/usb/callbacks.txt new file mode 100644 index 000000000000..7c812411945b --- /dev/null +++ b/Documentation/usb/callbacks.txt @@ -0,0 +1,132 @@ +What callbacks will usbcore do? +=============================== + +Usbcore will call into a driver through callbacks defined in the driver +structure and through the completion handler of URBs a driver submits. +Only the former are in the scope of this document. These two kinds of +callbacks are completely independent of each other. Information on the +completion callback can be found in Documentation/usb/URB.txt. + +The callbacks defined in the driver structure are: + +1. Hotplugging callbacks: + + * @probe: Called to see if the driver is willing to manage a particular + * interface on a device. + * @disconnect: Called when the interface is no longer accessible, usually + * because its device has been (or is being) disconnected or the + * driver module is being unloaded. + +2. Odd backdoor through usbfs: + + * @ioctl: Used for drivers that want to talk to userspace through + * the "usbfs" filesystem. This lets devices provide ways to + * expose information to user space regardless of where they + * do (or don't) show up otherwise in the filesystem. + +3. Power management (PM) callbacks: + + * @suspend: Called when the device is going to be suspended. + * @resume: Called when the device is being resumed. + * @reset_resume: Called when the suspended device has been reset instead + * of being resumed. + +4. Device level operations: + + * @pre_reset: Called when the device is about to be reset. + * @post_reset: Called after the device has been reset + +The ioctl interface (2) should be used only if you have a very good +reason. Sysfs is preferred these days. The PM callbacks are covered +separately in Documentation/usb/power-management.txt. + +Calling conventions +=================== + +All callbacks are mutually exclusive. There's no need for locking +against other USB callbacks. All callbacks are called from a task +context. You may sleep. However, it is important that all sleeps have a +small fixed upper limit in time. In particular you must not call out to +user space and await results. + +Hotplugging callbacks +===================== + +These callbacks are intended to associate and disassociate a driver with +an interface. A driver's bond to an interface is exclusive. + +The probe() callback +-------------------- + +int (*probe) (struct usb_interface *intf, + const struct usb_device_id *id); + +Accept or decline an interface. If you accept the device return 0, +otherwise -ENODEV or -ENXIO. Other error codes should be used only if a +genuine error occurred during initialisation which prevented a driver +from accepting a device that would else have been accepted. +You are strongly encouraged to use usbcore'sfacility, +usb_set_intfdata(), to associate a data structure with an interface, so +that you know which internal state and identity you associate with a +particular interface. The device will not be suspended and you may do IO +to the interface you are called for and endpoint 0 of the device. Device +initialisation that doesn't take too long is a good idea here. + +The disconnect() callback +------------------------- + +void (*disconnect) (struct usb_interface *intf); + +This callback is a signal to break any connection with an interface. +You are not allowed any IO to a device after returning from this +callback. You also may not do any other operation that may interfere +with another driver bound the interface, eg. a power management +operation. +If you are called due to a physical disconnection, all your URBs will be +killed by usbcore. Note that in this case disconnect will be called some +time after the physical disconnection. Thus your driver must be prepared +to deal with failing IO even prior to the callback. + +Device level callbacks +====================== + +pre_reset +--------- + +int (*pre_reset)(struct usb_interface *intf); + +Another driver or user space is triggering a reset on the device which +contains the interface passed as an argument. Cease IO and save any +device state you need to restore. + +If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you +are in atomic context. + +post_reset +---------- + +int (*post_reset)(struct usb_interface *intf); + +The reset has completed. Restore any saved device state and begin +using the device again. + +If you need to allocate memory here, use GFP_NOIO or GFP_ATOMIC, if you +are in atomic context. + +Call sequences +============== + +No callbacks other than probe will be invoked for an interface +that isn't bound to your driver. + +Probe will never be called for an interface bound to a driver. +Hence following a successful probe, disconnect will be called +before there is another probe for the same interface. + +Once your driver is bound to an interface, disconnect can be +called at any time except in between pre_reset and post_reset. +pre_reset is always followed by post_reset, even if the reset +failed or the device has been unplugged. + +suspend is always followed by one of: resume, reset_resume, or +disconnect. -- cgit v1.2.3 From f62220d3a9ccb879c3f90f845ae57b724b7bbb62 Mon Sep 17 00:00:00 2001 From: Andy Fleming Date: Fri, 18 Apr 2008 17:29:54 -0500 Subject: phylib: Add support for board-level PHY fixups Sometimes the specific interaction between the platform and the PHY requires special handling. For instance, to change where the PHY's clock input is, or to add a delay to account for latency issues in the data path. We add a mechanism for registering a callback with the PHY Lib to be called on matching PHYs when they are brought up, or reset. Signed-off-by: Andy Fleming Signed-off-by: Jeff Garzik --- Documentation/networking/phy.txt | 38 +++++++++++- drivers/net/phy/mdio_bus.c | 3 + drivers/net/phy/phy.c | 4 +- drivers/net/phy/phy_device.c | 129 +++++++++++++++++++++++++++++++++++---- include/linux/phy.h | 24 +++++++- 5 files changed, 182 insertions(+), 16 deletions(-) (limited to 'Documentation') diff --git a/Documentation/networking/phy.txt b/Documentation/networking/phy.txt index 0bc95eab1512..8df6a7b0e66c 100644 --- a/Documentation/networking/phy.txt +++ b/Documentation/networking/phy.txt @@ -1,7 +1,7 @@ ------- PHY Abstraction Layer -(Updated 2006-11-30) +(Updated 2008-04-08) Purpose @@ -291,3 +291,39 @@ Writing a PHY driver Feel free to look at the Marvell, Cicada, and Davicom drivers in drivers/net/phy/ for examples (the lxt and qsemi drivers have not been tested as of this writing) + +Board Fixups + + Sometimes the specific interaction between the platform and the PHY requires + special handling. For instance, to change where the PHY's clock input is, + or to add a delay to account for latency issues in the data path. In order + to support such contingencies, the PHY Layer allows platform code to register + fixups to be run when the PHY is brought up (or subsequently reset). + + When the PHY Layer brings up a PHY it checks to see if there are any fixups + registered for it, matching based on UID (contained in the PHY device's phy_id + field) and the bus identifier (contained in phydev->dev.bus_id). Both must + match, however two constants, PHY_ANY_ID and PHY_ANY_UID, are provided as + wildcards for the bus ID and UID, respectively. + + When a match is found, the PHY layer will invoke the run function associated + with the fixup. This function is passed a pointer to the phy_device of + interest. It should therefore only operate on that PHY. + + The platform code can either register the fixup using phy_register_fixup(): + + int phy_register_fixup(const char *phy_id, + u32 phy_uid, u32 phy_uid_mask, + int (*run)(struct phy_device *)); + + Or using one of the two stubs, phy_register_fixup_for_uid() and + phy_register_fixup_for_id(): + + int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, + int (*run)(struct phy_device *)); + int phy_register_fixup_for_id(const char *phy_id, + int (*run)(struct phy_device *)); + + The stubs set one of the two matching criteria, and set the other one to + match anything. + diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c index 963630c65ca9..94e0b7ed76f1 100644 --- a/drivers/net/phy/mdio_bus.c +++ b/drivers/net/phy/mdio_bus.c @@ -89,6 +89,9 @@ int mdiobus_register(struct mii_bus *bus) phydev->bus = bus; + /* Run all of the fixups for this PHY */ + phy_scan_fixups(phydev); + err = device_register(&phydev->dev); if (err) { diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 12fccb1c76dc..3c18bb594957 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -406,8 +406,10 @@ int phy_mii_ioctl(struct phy_device *phydev, if (mii_data->reg_num == MII_BMCR && val & BMCR_RESET - && phydev->drv->config_init) + && phydev->drv->config_init) { + phy_scan_fixups(phydev); phydev->drv->config_init(phydev); + } break; default: diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 8b1121b02f98..ddf8d51832a6 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -53,6 +53,96 @@ static void phy_device_release(struct device *dev) phy_device_free(to_phy_device(dev)); } +static LIST_HEAD(phy_fixup_list); +static DEFINE_MUTEX(phy_fixup_lock); + +/* + * Creates a new phy_fixup and adds it to the list + * @bus_id: A string which matches phydev->dev.bus_id (or PHY_ANY_ID) + * @phy_uid: Used to match against phydev->phy_id (the UID of the PHY) + * It can also be PHY_ANY_UID + * @phy_uid_mask: Applied to phydev->phy_id and fixup->phy_uid before + * comparison + * @run: The actual code to be run when a matching PHY is found + */ +int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask, + int (*run)(struct phy_device *)) +{ + struct phy_fixup *fixup; + + fixup = kzalloc(sizeof(struct phy_fixup), GFP_KERNEL); + if (!fixup) + return -ENOMEM; + + strncpy(fixup->bus_id, bus_id, BUS_ID_SIZE); + fixup->phy_uid = phy_uid; + fixup->phy_uid_mask = phy_uid_mask; + fixup->run = run; + + mutex_lock(&phy_fixup_lock); + list_add_tail(&fixup->list, &phy_fixup_list); + mutex_unlock(&phy_fixup_lock); + + return 0; +} +EXPORT_SYMBOL(phy_register_fixup); + +/* Registers a fixup to be run on any PHY with the UID in phy_uid */ +int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, + int (*run)(struct phy_device *)) +{ + return phy_register_fixup(PHY_ANY_ID, phy_uid, phy_uid_mask, run); +} +EXPORT_SYMBOL(phy_register_fixup_for_uid); + +/* Registers a fixup to be run on the PHY with id string bus_id */ +int phy_register_fixup_for_id(const char *bus_id, + int (*run)(struct phy_device *)) +{ + return phy_register_fixup(bus_id, PHY_ANY_UID, 0xffffffff, run); +} +EXPORT_SYMBOL(phy_register_fixup_for_id); + +/* + * Returns 1 if fixup matches phydev in bus_id and phy_uid. + * Fixups can be set to match any in one or more fields. + */ +static int phy_needs_fixup(struct phy_device *phydev, struct phy_fixup *fixup) +{ + if (strcmp(fixup->bus_id, phydev->dev.bus_id) != 0) + if (strcmp(fixup->bus_id, PHY_ANY_ID) != 0) + return 0; + + if ((fixup->phy_uid & fixup->phy_uid_mask) != + (phydev->phy_id & fixup->phy_uid_mask)) + if (fixup->phy_uid != PHY_ANY_UID) + return 0; + + return 1; +} + +/* Runs any matching fixups for this phydev */ +int phy_scan_fixups(struct phy_device *phydev) +{ + struct phy_fixup *fixup; + + mutex_lock(&phy_fixup_lock); + list_for_each_entry(fixup, &phy_fixup_list, list) { + if (phy_needs_fixup(phydev, fixup)) { + int err; + + err = fixup->run(phydev); + + if (err < 0) + return err; + } + } + mutex_unlock(&phy_fixup_lock); + + return 0; +} +EXPORT_SYMBOL(phy_scan_fixups); + struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id) { struct phy_device *dev; @@ -179,13 +269,13 @@ void phy_prepare_link(struct phy_device *phydev, * choose to call only the subset of functions which provide * the desired functionality. */ -struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, +struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, void (*handler)(struct net_device *), u32 flags, phy_interface_t interface) { struct phy_device *phydev; - phydev = phy_attach(dev, phy_id, flags, interface); + phydev = phy_attach(dev, bus_id, flags, interface); if (IS_ERR(phydev)) return phydev; @@ -226,7 +316,7 @@ static int phy_compare_id(struct device *dev, void *data) /** * phy_attach - attach a network device to a particular PHY device * @dev: network device to attach - * @phy_id: PHY device to attach + * @bus_id: PHY device to attach * @flags: PHY device's dev_flags * @interface: PHY device's interface * @@ -238,7 +328,7 @@ static int phy_compare_id(struct device *dev, void *data) * change. The phy_device is returned to the attaching driver. */ struct phy_device *phy_attach(struct net_device *dev, - const char *phy_id, u32 flags, phy_interface_t interface) + const char *bus_id, u32 flags, phy_interface_t interface) { struct bus_type *bus = &mdio_bus_type; struct phy_device *phydev; @@ -246,12 +336,12 @@ struct phy_device *phy_attach(struct net_device *dev, /* Search the list of PHY devices on the mdio bus for the * PHY with the requested name */ - d = bus_find_device(bus, NULL, (void *)phy_id, phy_compare_id); + d = bus_find_device(bus, NULL, (void *)bus_id, phy_compare_id); if (d) { phydev = to_phy_device(d); } else { - printk(KERN_ERR "%s not found\n", phy_id); + printk(KERN_ERR "%s not found\n", bus_id); return ERR_PTR(-ENODEV); } @@ -271,7 +361,7 @@ struct phy_device *phy_attach(struct net_device *dev, if (phydev->attached_dev) { printk(KERN_ERR "%s: %s already attached\n", - dev->name, phy_id); + dev->name, bus_id); return ERR_PTR(-EBUSY); } @@ -287,6 +377,11 @@ struct phy_device *phy_attach(struct net_device *dev, if (phydev->drv->config_init) { int err; + err = phy_scan_fixups(phydev); + + if (err < 0) + return ERR_PTR(err); + err = phydev->drv->config_init(phydev); if (err < 0) @@ -395,6 +490,7 @@ EXPORT_SYMBOL(genphy_config_advert); */ int genphy_setup_forced(struct phy_device *phydev) { + int err; int ctl = 0; phydev->pause = phydev->asym_pause = 0; @@ -407,17 +503,26 @@ int genphy_setup_forced(struct phy_device *phydev) if (DUPLEX_FULL == phydev->duplex) ctl |= BMCR_FULLDPLX; - ctl = phy_write(phydev, MII_BMCR, ctl); + err = phy_write(phydev, MII_BMCR, ctl); - if (ctl < 0) - return ctl; + if (err < 0) + return err; + + /* + * Run the fixups on this PHY, just in case the + * board code needs to change something after a reset + */ + err = phy_scan_fixups(phydev); + + if (err < 0) + return err; /* We just reset the device, so we'd better configure any * settings the PHY requires to operate */ if (phydev->drv->config_init) - ctl = phydev->drv->config_init(phydev); + err = phydev->drv->config_init(phydev); - return ctl; + return err; } diff --git a/include/linux/phy.h b/include/linux/phy.h index 779cbcd65f62..02df20f085fe 100644 --- a/include/linux/phy.h +++ b/include/linux/phy.h @@ -379,6 +379,18 @@ struct phy_driver { }; #define to_phy_driver(d) container_of(d, struct phy_driver, driver) +#define PHY_ANY_ID "MATCH ANY PHY" +#define PHY_ANY_UID 0xffffffff + +/* A Structure for boards to register fixups with the PHY Lib */ +struct phy_fixup { + struct list_head list; + char bus_id[BUS_ID_SIZE]; + u32 phy_uid; + u32 phy_uid_mask; + int (*run)(struct phy_device *phydev); +}; + int phy_read(struct phy_device *phydev, u16 regnum); int phy_write(struct phy_device *phydev, u16 regnum, u16 val); int get_phy_id(struct mii_bus *bus, int addr, u32 *phy_id); @@ -386,8 +398,8 @@ struct phy_device* get_phy_device(struct mii_bus *bus, int addr); int phy_clear_interrupt(struct phy_device *phydev); int phy_config_interrupt(struct phy_device *phydev, u32 interrupts); struct phy_device * phy_attach(struct net_device *dev, - const char *phy_id, u32 flags, phy_interface_t interface); -struct phy_device * phy_connect(struct net_device *dev, const char *phy_id, + const char *bus_id, u32 flags, phy_interface_t interface); +struct phy_device * phy_connect(struct net_device *dev, const char *bus_id, void (*handler)(struct net_device *), u32 flags, phy_interface_t interface); void phy_disconnect(struct phy_device *phydev); @@ -427,5 +439,13 @@ void phy_print_status(struct phy_device *phydev); struct phy_device* phy_device_create(struct mii_bus *bus, int addr, int phy_id); void phy_device_free(struct phy_device *phydev); +int phy_register_fixup(const char *bus_id, u32 phy_uid, u32 phy_uid_mask, + int (*run)(struct phy_device *)); +int phy_register_fixup_for_id(const char *bus_id, + int (*run)(struct phy_device *)); +int phy_register_fixup_for_uid(u32 phy_uid, u32 phy_uid_mask, + int (*run)(struct phy_device *)); +int phy_scan_fixups(struct phy_device *phydev); + extern struct bus_type mdio_bus_type; #endif /* __PHY_H */ -- cgit v1.2.3 From e3dcc5a387fc38e9c3c6c4f857cd9a7f71a8553a Mon Sep 17 00:00:00 2001 From: Milan Broz Date: Thu, 24 Apr 2008 22:11:03 +0100 Subject: dm crypt: add documentation Add description of dm-crypt to device-mapper documentation. Signed-off-by: Milan Broz Signed-off-by: Alasdair G Kergon --- Documentation/device-mapper/dm-crypt.txt | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 Documentation/device-mapper/dm-crypt.txt (limited to 'Documentation') diff --git a/Documentation/device-mapper/dm-crypt.txt b/Documentation/device-mapper/dm-crypt.txt new file mode 100644 index 000000000000..6680cab2c705 --- /dev/null +++ b/Documentation/device-mapper/dm-crypt.txt @@ -0,0 +1,52 @@ +dm-crypt +========= + +Device-Mapper's "crypt" target provides transparent encryption of block devices +using the kernel crypto API. + +Parameters: + + + Encryption cipher and an optional IV generation mode. + (In format cipher-chainmode-ivopts:ivmode). + Examples: + des + aes-cbc-essiv:sha256 + twofish-ecb + + /proc/crypto contains supported crypto modes + + + Key used for encryption. It is encoded as a hexadecimal number. + You can only use key sizes that are valid for the selected cipher. + + + The IV offset is a sector count that is added to the sector number + before creating the IV. + + + This is the device that is going to be used as backend and contains the + encrypted data. You can specify it as a path like /dev/xxx or a device + number :. + + + Starting sector within the device where the encrypted data begins. + +Example scripts +=============== +LUKS (Linux Unified Key Setup) is now the preferred way to set up disk +encryption with dm-crypt using the 'cryptsetup' utility, see +http://luks.endorphin.org/ + +[[ +#!/bin/sh +# Create a crypt device using dmsetup +dmsetup create crypt1 --table "0 `blockdev --getsize $1` crypt aes-cbc-essiv:sha256 babebabebabebabebabebabebabebabe 0 $1 0" +]] + +[[ +#!/bin/sh +# Create a crypt device using cryptsetup and LUKS header with default cipher +cryptsetup luksFormat $1 +cryptsetup luksOpen $1 crypt1 +]] -- cgit v1.2.3 From c272cca625ab507e7cc23708ee5c64d2f384708f Mon Sep 17 00:00:00 2001 From: James Lentini Date: Thu, 24 Apr 2008 15:57:43 -0400 Subject: Update to NFS/RDMA documentation Update to the NFS/RDMA documentation to clarify how to configure the exports file. Signed-off-by: James Lentini Signed-off-by: J. Bruce Fields --- Documentation/filesystems/nfs-rdma.txt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/nfs-rdma.txt b/Documentation/filesystems/nfs-rdma.txt index 1ae34879574b..d0ec45ae4e7d 100644 --- a/Documentation/filesystems/nfs-rdma.txt +++ b/Documentation/filesystems/nfs-rdma.txt @@ -5,7 +5,7 @@ ################################################################################ Author: NetApp and Open Grid Computing - Date: February 25, 2008 + Date: April 15, 2008 Table of Contents ~~~~~~~~~~~~~~~~~ @@ -197,12 +197,16 @@ NFS/RDMA Setup - On the server system, configure the /etc/exports file and start the NFS/RDMA server. - Exports entries with the following format have been tested: + Exports entries with the following formats have been tested: - /vol0 10.97.103.47(rw,async) 192.168.0.47(rw,async,insecure,no_root_squash) + /vol0 192.168.0.47(fsid=0,rw,async,insecure,no_root_squash) + /vol0 192.168.0.0/255.255.255.0(fsid=0,rw,async,insecure,no_root_squash) - Here the first IP address is the client's Ethernet address and the second - IP address is the clients IPoIB address. + The IP address(es) is(are) the client's IPoIB address for an InfiniBand HCA or the + cleint's iWARP address(es) for an RNIC. + + NOTE: The "insecure" option must be used because the NFS/RDMA client does not + use a reserved port. Each time a machine boots: -- cgit v1.2.3 From 0fe8a3ce73ef31d1480e82798503948a979e8e52 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 25 Apr 2008 11:23:56 -0600 Subject: Various fixes to Documentation/HOWTO Fix a number of things which have gone somewhat out-of-date over the last few months. Signed-off-by: Jonathan Corbet --- Documentation/HOWTO | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) (limited to 'Documentation') diff --git a/Documentation/HOWTO b/Documentation/HOWTO index 54835610b3d6..0291ade44c17 100644 --- a/Documentation/HOWTO +++ b/Documentation/HOWTO @@ -249,9 +249,11 @@ process is as follows: release a new -rc kernel every week. - Process continues until the kernel is considered "ready", the process should last around 6 weeks. - - A list of known regressions present in each -rc release is - tracked at the following URI: - http://kernelnewbies.org/known_regressions + - Known regressions in each release are periodically posted to the + linux-kernel mailing list. The goal is to reduce the length of + that list to zero before declaring the kernel to be "ready," but, in + the real world, a small number of regressions often remain at + release time. It is worth mentioning what Andrew Morton wrote on the linux-kernel mailing list about kernel releases: @@ -261,7 +263,7 @@ mailing list about kernel releases: 2.6.x.y -stable kernel tree --------------------------- -Kernels with 4 digit versions are -stable kernels. They contain +Kernels with 4-part versions are -stable kernels. They contain relatively small and critical fixes for security problems or significant regressions discovered in a given 2.6.x kernel. @@ -273,7 +275,10 @@ If no 2.6.x.y kernel is available, then the highest numbered 2.6.x kernel is the current stable kernel. 2.6.x.y are maintained by the "stable" team , and are -released almost every other week. +released as needs dictate. The normal release period is approximately +two weeks, but it can be longer if there are no pressing problems. A +security-related problem, instead, can cause a release to happen almost +instantly. The file Documentation/stable_kernel_rules.txt in the kernel tree documents what kinds of changes are acceptable for the -stable tree, and @@ -298,7 +303,9 @@ a while Andrew or the subsystem maintainer pushes it on to Linus for inclusion in mainline. It is heavily encouraged that all new patches get tested in the -mm tree -before they are sent to Linus for inclusion in the main kernel tree. +before they are sent to Linus for inclusion in the main kernel tree. Code +which does not make an appearance in -mm before the opening of the merge +window will prove hard to merge into the mainline. These kernels are not appropriate for use on systems that are supposed to be stable and they are more risky to run than any of the other @@ -354,11 +361,12 @@ Here is a list of some of the different kernel trees available: - SCSI, James Bottomley git.kernel.org:/pub/scm/linux/kernel/git/jejb/scsi-misc-2.6.git + - x86, Ingo Molnar + git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86.git + quilt trees: - - USB, PCI, Driver Core, and I2C, Greg Kroah-Hartman + - USB, Driver Core, and I2C, Greg Kroah-Hartman kernel.org/pub/linux/kernel/people/gregkh/gregkh-2.6/ - - x86-64, partly i386, Andi Kleen - ftp.firstfloor.org:/pub/ak/x86_64/quilt/ Other kernel trees can be found listed at http://git.kernel.org/ and in the MAINTAINERS file. @@ -392,8 +400,8 @@ If you want to be advised of the future bug reports, you can subscribe to the bugme-new mailing list (only new bug reports are mailed here) or to the bugme-janitor mailing list (every change in the bugzilla is mailed here) - http://lists.osdl.org/mailman/listinfo/bugme-new - http://lists.osdl.org/mailman/listinfo/bugme-janitors + http://lists.linux-foundation.org/mailman/listinfo/bugme-new + http://lists.linux-foundation.org/mailman/listinfo/bugme-janitors -- cgit v1.2.3 From 9f4def9ae4772ea3da5e2359de698742ebae53b5 Mon Sep 17 00:00:00 2001 From: Jonathan Corbet Date: Fri, 25 Apr 2008 11:56:37 -0600 Subject: Document seq_path_root() Signed-off-by: Jonathan Corbet --- Documentation/filesystems/seq_file.txt | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/seq_file.txt b/Documentation/filesystems/seq_file.txt index 0ab92c260894..b843743aa0b5 100644 --- a/Documentation/filesystems/seq_file.txt +++ b/Documentation/filesystems/seq_file.txt @@ -187,12 +187,18 @@ The first two output a single character and a string, just like one would expect. seq_escape() is like seq_puts(), except that any character in s which is in the string esc will be represented in octal form in the output. -There is also a function for printing filenames: +There is also a pair of functions for printing filenames: int seq_path(struct seq_file *m, struct path *path, char *esc); + int seq_path_root(struct seq_file *m, struct path *path, + struct path *root, char *esc) Here, path indicates the file of interest, and esc is a set of characters -which should be escaped in the output. +which should be escaped in the output. A call to seq_path() will output +the path relative to the current process's filesystem root. If a different +root is desired, it can be used with seq_path_root(). Note that, if it +turns out that path cannot be reached from root, the value of root will be +changed in seq_file_root() to a root which *does* work. Making it all work -- cgit v1.2.3 From 0d96fb20b7ed757fc936bb35e26c22251a75b734 Mon Sep 17 00:00:00 2001 From: Richard Hacker Date: Thu, 28 Feb 2008 09:40:58 +0100 Subject: kbuild: Add new Kbuild variable KBUILD_EXTRA_SYMBOLS This patch adds a new (Kbuild) Makefile variable KBUILD_EXTRA_SYMBOLS. The space separated list of file names assigned to KBUILD_EXTRA_SYMBOLS is used when calling scripts/mod/modpost during stage 2 of the Kbuild process for non-kernel-tree modules. Signed-off-by: Richard Hacker Signed-off-by: Sam Ravnborg --- Documentation/kbuild/modules.txt | 9 ++++++++- scripts/Makefile.modpost | 8 ++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/kbuild/modules.txt b/Documentation/kbuild/modules.txt index 1d247d59ad56..1821c077b435 100644 --- a/Documentation/kbuild/modules.txt +++ b/Documentation/kbuild/modules.txt @@ -486,7 +486,7 @@ Module.symvers contains a list of all exported symbols from a kernel build. Sometimes, an external module uses exported symbols from another external module. Kbuild needs to have full knowledge on all symbols to avoid spitting out warnings about undefined symbols. - Two solutions exist to let kbuild know all symbols of more than + Three solutions exist to let kbuild know all symbols of more than one external module. The method with a top-level kbuild file is recommended but may be impractical in certain situations. @@ -523,6 +523,13 @@ Module.symvers contains a list of all exported symbols from a kernel build. containing the sum of all symbols defined and not part of the kernel. + Use make variable KBUILD_EXTRA_SYMBOLS in the Makefile + If it is impractical to copy Module.symvers from another + module, you can assign a space separated list of files to + KBUILD_EXTRA_SYMBOLS in your Makfile. These files will be + loaded by modpost during the initialisation of its symbol + tables. + === 8. Tips & Tricks --- 8.1 Testing for CONFIG_FOO_BAR diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost index 2d20640854b7..24b3c8fe6bca 100644 --- a/scripts/Makefile.modpost +++ b/scripts/Makefile.modpost @@ -42,6 +42,13 @@ _modpost: __modpost include include/config/auto.conf include scripts/Kbuild.include + +ifneq ($(KBUILD_EXTMOD),) +# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS +include $(if $(wildcard $(KBUILD_EXTMOD)/Kbuild), \ + $(KBUILD_EXTMOD)/Kbuild, $(KBUILD_EXTMOD)/Makefile) +endif + include scripts/Makefile.lib kernelsymfile := $(objtree)/Module.symvers @@ -69,6 +76,7 @@ modpost = scripts/mod/modpost \ $(if $(CONFIG_MODULE_SRCVERSION_ALL),-a,) \ $(if $(KBUILD_EXTMOD),-i,-o) $(kernelsymfile) \ $(if $(KBUILD_EXTMOD),-I $(modulesymfile)) \ + $(if $(iKBUILD_EXTRA_SYMBOLS), $(patsubst %, -e %,$(EXTRA_SYMBOLS))) \ $(if $(KBUILD_EXTMOD),-o $(modulesymfile)) \ $(if $(CONFIG_DEBUG_SECTION_MISMATCH),,-S) \ $(if $(CONFIG_MARKERS),-K $(kernelmarkersfile)) \ -- cgit v1.2.3 From 759cd603beea7f4ab7df1e6bcfda90b62b5f4125 Mon Sep 17 00:00:00 2001 From: Mike Frysinger Date: Fri, 28 Mar 2008 14:30:58 -0700 Subject: kbuild: silence documentation GEN xml messages according to $(quiet) Add rules for gen_xml and its quiet & silent variants. This causes "make -s" to be silent for gen_xml. Signed-off-by: Mike Frysinger Acked-by: Randy Dunlap Signed-off-by: Andrew Morton Signed-off-by: Sam Ravnborg --- Documentation/DocBook/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'Documentation') diff --git a/Documentation/DocBook/Makefile b/Documentation/DocBook/Makefile index b2b6366bba51..83966e94cc32 100644 --- a/Documentation/DocBook/Makefile +++ b/Documentation/DocBook/Makefile @@ -187,8 +187,11 @@ quiet_cmd_fig2png = FIG2PNG $@ ### # Rule to convert a .c file to inline XML documentation + gen_xml = : + quiet_gen_xml = echo ' GEN $@' +silent_gen_xml = : %.xml: %.c - @echo ' GEN $@' + @$($(quiet)gen_xml) @( \ echo ""; \ expand --tabs=8 < $< | \ -- cgit v1.2.3 From 753d7054c318f323a7c135c71c68171a6b6a88fc Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 25 Apr 2008 16:38:44 -0700 Subject: documentation: remove smart-config.txt As requested by Sam Ravnborg: Remove Documentation/smart-config.txt. It is outdated and has been (functionally) replaced by Documentation/kbuild/*.txt. Signed-off-by: Randy Dunlap Signed-off-by: Linus Torvalds --- Documentation/00-INDEX | 2 - Documentation/smart-config.txt | 98 ------------------------------------------ 2 files changed, 100 deletions(-) delete mode 100644 Documentation/smart-config.txt (limited to 'Documentation') diff --git a/Documentation/00-INDEX b/Documentation/00-INDEX index a82a113b4a4b..1977fab38656 100644 --- a/Documentation/00-INDEX +++ b/Documentation/00-INDEX @@ -329,8 +329,6 @@ sgi-visws.txt - short blurb on the SGI Visual Workstations. sh/ - directory with info on porting Linux to a new architecture. -smart-config.txt - - description of the Smart Config makefile feature. sound/ - directory with info on sound card support. sparc/ diff --git a/Documentation/smart-config.txt b/Documentation/smart-config.txt deleted file mode 100644 index 8467447b5a87..000000000000 --- a/Documentation/smart-config.txt +++ /dev/null @@ -1,98 +0,0 @@ -Smart CONFIG_* Dependencies -1 August 1999 - -Michael Chastain -Werner Almesberger -Martin von Loewis - -Here is the problem: - - Suppose that drivers/net/foo.c has the following lines: - - #include - - ... - - #ifdef CONFIG_FOO_AUTOFROB - /* Code for auto-frobbing */ - #else - /* Manual frobbing only */ - #endif - - ... - - #ifdef CONFIG_FOO_MODEL_TWO - /* Code for model two */ - #endif - - Now suppose the user (the person building kernels) reconfigures the - kernel to change some unrelated setting. This will regenerate the - file include/linux/autoconf.h, which will cause include/linux/config.h - to be out of date, which will cause drivers/net/foo.c to be recompiled. - - Most kernel sources, perhaps 80% of them, have at least one CONFIG_* - dependency somewhere. So changing _any_ CONFIG_* setting requires - almost _all_ of the kernel to be recompiled. - -Here is the solution: - - We've made the dependency generator, mkdep.c, smarter. Instead of - generating this dependency: - - drivers/net/foo.c: include/linux/config.h - - It now generates these dependencies: - - drivers/net/foo.c: \ - include/config/foo/autofrob.h \ - include/config/foo/model/two.h - - So drivers/net/foo.c depends only on the CONFIG_* lines that - it actually uses. - - A new program, split-include.c, runs at the beginning of - compilation (make bzImage or make zImage). split-include reads - include/linux/autoconf.h and updates the include/config/ tree, - writing one file per option. It updates only the files for options - that have changed. - -Flag Dependencies - - Martin Von Loewis contributed another feature to this patch: - 'flag dependencies'. The idea is that a .o file depends on - the compilation flags used to build it. The file foo.o has - its flags stored in .flags.foo.o. - - Suppose the user changes the foo driver from resident to modular. - 'make' will notice that the current foo.o was not compiled with - -DMODULE and will recompile foo.c. - - All .o files made from C source have flag dependencies. So do .o - files made with ld, and .a files made with ar. However, .o files - made from assembly source do not have flag dependencies (nobody - needs this yet, but it would be good to fix). - -Per-source-file Flags - - Flag dependencies also work with per-source-file flags. - You can specify compilation flags for individual source files - like this: - - CFLAGS_foo.o = -DSPECIAL_FOO_DEFINE - - This helps clean up drivers/net/Makefile, drivers/scsi/Makefile, - and several other Makefiles. - -Credit - - Werner Almesberger had the original idea and wrote the first - version of this patch. - - Michael Chastain picked it up and continued development. He is - now the principal author and maintainer. Please report any bugs - to him. - - Martin von Loewis wrote flag dependencies, with some modifications - by Michael Chastain. - - Thanks to all of the beta testers. -- cgit v1.2.3 From fb884381273669fad034538e6cb186678407cf22 Mon Sep 17 00:00:00 2001 From: "Huang, Ying" Date: Fri, 28 Mar 2008 10:49:50 +0800 Subject: x86, boot: Document for linked list of struct setup_data Documentation for linked list of struct setup_data. Signed-off-by: Huang Ying Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner --- Documentation/i386/boot.txt | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'Documentation') diff --git a/Documentation/i386/boot.txt b/Documentation/i386/boot.txt index 2eb16100bb3f..0fac3465f2e3 100644 --- a/Documentation/i386/boot.txt +++ b/Documentation/i386/boot.txt @@ -42,6 +42,8 @@ Protocol 2.05: (Kernel 2.6.20) Make protected mode kernel relocatable. Protocol 2.06: (Kernel 2.6.22) Added a field that contains the size of the boot command line +Protocol 2.09: (kernel 2.6.26) Added a field of 64-bit physical + pointer to single linked list of struct setup_data. **** MEMORY LAYOUT @@ -172,6 +174,8 @@ Offset Proto Name Meaning 0240/8 2.07+ hardware_subarch_data Subarchitecture-specific data 0248/4 2.08+ payload_offset Offset of kernel payload 024C/4 2.08+ payload_length Length of kernel payload +0250/8 2.09+ setup_data 64-bit physical pointer to linked list + of struct setup_data (1) For backwards compatibility, if the setup_sects field contains 0, the real value is 4. @@ -572,6 +576,28 @@ command line is entered using the following protocol: covered by setup_move_size, so you may need to adjust this field. +Field name: setup_data +Type: write (obligatory) +Offset/size: 0x250/8 +Protocol: 2.09+ + + The 64-bit physical pointer to NULL terminated single linked list of + struct setup_data. This is used to define a more extensible boot + parameters passing mechanism. The definition of struct setup_data is + as follow: + + struct setup_data { + u64 next; + u32 type; + u32 len; + u8 data[0]; + }; + + Where, the next is a 64-bit physical pointer to the next node of + linked list, the next field of the last node is 0; the type is used + to identify the contents of data; the len is the length of data + field; the data holds the real payload. + **** MEMORY LAYOUT OF THE REAL-MODE CODE -- cgit v1.2.3 From f629b38beddf2ff8bc3fda1754bbd6cc7d3acc03 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sat, 26 Apr 2008 22:25:22 +0200 Subject: au1xxx-ide: fix MWDMA support Always use "fast" MWDMA support and remove dma_{black,white}_list (they were based on completely bogus ->ide_dma_check implementation which didn't set neither the host controller timings nor the device for the desired transfer mode). Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/mips/AU1xxx_IDE.README | 46 ----------------------------- drivers/ide/mips/au1xxx-ide.c | 49 ++----------------------------- include/asm-mips/mach-au1x00/au1xxx_ide.h | 42 -------------------------- 3 files changed, 2 insertions(+), 135 deletions(-) (limited to 'Documentation') diff --git a/Documentation/mips/AU1xxx_IDE.README b/Documentation/mips/AU1xxx_IDE.README index 5c8334123f4f..25a6ed1aaa5b 100644 --- a/Documentation/mips/AU1xxx_IDE.README +++ b/Documentation/mips/AU1xxx_IDE.README @@ -46,8 +46,6 @@ Two files are introduced: a) 'include/asm-mips/mach-au1x00/au1xxx_ide.h' containes : struct _auide_hwif - struct drive_list_entry dma_white_list - struct drive_list_entry dma_black_list timing parameters for PIO mode 0/1/2/3/4 timing parameters for MWDMA 0/1/2 @@ -63,12 +61,6 @@ Four configs variables are introduced: CONFIG_BLK_DEV_IDE_AU1XXX_SEQTS_PER_RQ - maximum transfer size per descriptor -If MWDMA is enabled and the connected hard disc is not on the white list, the -kernel switches to a "safe mwdma mode" at boot time. In this mode the IDE -performance is substantial slower then in full speed mwdma. In this case -please add your hard disc to the white list (follow instruction from 'ADD NEW -HARD DISC TO WHITE OR BLACK LIST' section). - SUPPORTED IDE MODES ------------------- @@ -120,44 +112,6 @@ CONFIG_IDEDMA_AUTO=y Also undefine 'IDE_AU1XXX_BURSTMODE' in 'drivers/ide/mips/au1xxx-ide.c' to disable the burst support on DBDMA controller. -ADD NEW HARD DISC TO WHITE OR BLACK LIST ----------------------------------------- - -Step 1 : detect the model name of your hard disc - - a) connect your hard disc to the AU1XXX - - b) boot your kernel and get the hard disc model. - - Example boot log: - - --snipped-- - Uniform Multi-Platform E-IDE driver Revision: 7.00alpha2 - ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx - Au1xxx IDE(builtin) configured for MWDMA2 - Probing IDE interface ide0... - hda: Maxtor 6E040L0, ATA DISK drive - ide0 at 0xac800000-0xac800007,0xac8001c0 on irq 64 - hda: max request size: 64KiB - hda: 80293248 sectors (41110 MB) w/2048KiB Cache, CHS=65535/16/63, (U)DMA - --snipped-- - - In this example 'Maxtor 6E040L0'. - -Step 2 : edit 'include/asm-mips/mach-au1x00/au1xxx_ide.h' - - Add your hard disc to the dma_white_list or dma_black_list structur. - -Step 3 : Recompile the kernel - - Enable MWDMA support in the kernel configuration. Recompile the kernel and - reboot. - -Step 4 : Tests - - If you have add a hard disc to the white list, please run some stress tests - for verification. - ACKNOWLEDGMENTS --------------- diff --git a/drivers/ide/mips/au1xxx-ide.c b/drivers/ide/mips/au1xxx-ide.c index 7179d4953211..d2e926efd3cc 100644 --- a/drivers/ide/mips/au1xxx-ide.c +++ b/drivers/ide/mips/au1xxx-ide.c @@ -47,7 +47,6 @@ #define IDE_AU1XXX_BURSTMODE 1 static _auide_hwif auide_hwif; -static int dbdma_init_done; static int auide_ddma_init(_auide_hwif *auide); @@ -315,35 +314,6 @@ static int auide_dma_setup(ide_drive_t *drive) return 0; } -static u8 auide_mdma_filter(ide_drive_t *drive) -{ - /* - * FIXME: ->white_list and ->black_list are based on completely bogus - * ->ide_dma_check implementation which didn't set neither the host - * controller timings nor the device for the desired transfer mode. - * - * They should be either removed or 0x00 MWDMA mask should be - * returned for devices on the ->black_list. - */ - - if (dbdma_init_done == 0) { - auide_hwif.white_list = ide_in_drive_list(drive->id, - dma_white_list); - auide_hwif.black_list = ide_in_drive_list(drive->id, - dma_black_list); - auide_hwif.drive = drive; - auide_ddma_init(&auide_hwif); - dbdma_init_done = 1; - } - - /* Is the drive in our DMA black list? */ - if (auide_hwif.black_list) - printk(KERN_WARNING "%s: Disabling DMA for %s (blacklisted)\n", - drive->name, drive->id->model); - - return drive->hwif->mwdma_mask; -} - static int auide_dma_test_irq(ide_drive_t *drive) { if (drive->waiting_for_dma == 0) @@ -420,17 +390,8 @@ static int auide_ddma_init(_auide_hwif *auide) { dev_id = AU1XXX_ATA_DDMA_REQ; - if (auide->white_list || auide->black_list) { - tsize = 8; - devwidth = 32; - } - else { - tsize = 1; - devwidth = 16; - - printk(KERN_ERR "au1xxx-ide: %s is not on ide driver whitelist.\n",auide_hwif.drive->id->model); - printk(KERN_ERR " please read 'Documentation/mips/AU1xxx_IDE.README'"); - } + tsize = 8; /* 1 */ + devwidth = 32; /* 16 */ #ifdef IDE_AU1XXX_BURSTMODE flags = DEV_FLAGS_SYNC | DEV_FLAGS_BURSTABLE; @@ -546,9 +507,6 @@ static void auide_setup_ports(hw_regs_t *hw, _auide_hwif *ahwif) static const struct ide_port_ops au1xxx_port_ops = { .set_pio_mode = au1xxx_set_pio_mode, .set_dma_mode = auide_set_dma_mode, -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA - .mdma_filter = auide_mdma_filter, -#endif }; static const struct ide_port_info au1xxx_port_info = { @@ -648,10 +606,7 @@ static int au_ide_probe(struct device *dev) auide_hwif.hwif = hwif; hwif->hwif_data = &auide_hwif; -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_PIO_DBDMA auide_ddma_init(&auide_hwif); - dbdma_init_done = 1; -#endif idx[0] = hwif->index; diff --git a/include/asm-mips/mach-au1x00/au1xxx_ide.h b/include/asm-mips/mach-au1x00/au1xxx_ide.h index 89655c0cdcd6..b493a5e46c63 100644 --- a/include/asm-mips/mach-au1x00/au1xxx_ide.h +++ b/include/asm-mips/mach-au1x00/au1xxx_ide.h @@ -70,7 +70,6 @@ typedef struct ide_hwif_t *hwif; #ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA ide_drive_t *drive; - u8 white_list, black_list; struct dbdma_cmd *dma_table_cpu; dma_addr_t dma_table_dma; #endif @@ -81,47 +80,6 @@ typedef struct #endif } _auide_hwif; -#ifdef CONFIG_BLK_DEV_IDE_AU1XXX_MDMA2_DBDMA -/* HD white list */ -static const struct drive_list_entry dma_white_list [] = { -/* - * Hitachi - */ - { "HITACHI_DK14FA-20" , NULL }, - { "HTS726060M9AT00" , NULL }, -/* - * Maxtor - */ - { "Maxtor 6E040L0" , NULL }, - { "Maxtor 6Y080P0" , NULL }, - { "Maxtor 6Y160P0" , NULL }, -/* - * Seagate - */ - { "ST3120026A" , NULL }, - { "ST320014A" , NULL }, - { "ST94011A" , NULL }, - { "ST340016A" , NULL }, -/* - * Western Digital - */ - { "WDC WD400UE-00HCT0" , NULL }, - { "WDC WD400JB-00JJC0" , NULL }, - { NULL , NULL } -}; - -/* HD black list */ -static const struct drive_list_entry dma_black_list [] = { -/* - * Western Digital - */ - { "WDC WD100EB-00CGH0" , NULL }, - { "WDC WD200BB-00AUA1" , NULL }, - { "WDC AC24300L" , NULL }, - { NULL , NULL } -}; -#endif - /******************************************************************************* * PIO Mode timing calculation : * * * -- cgit v1.2.3 From 5ecee4ba4eb2ada7ece7c41eb08cf7bc51b579e2 Mon Sep 17 00:00:00 2001 From: Carsten Otte Date: Tue, 25 Mar 2008 18:47:38 +0100 Subject: KVM: s390: API documentation This patch adds Documentation/s390/kvm.txt, which describes specifics of kvm's user interface that are unique to s390 architecture. Signed-off-by: Carsten Otte Signed-off-by: Avi Kivity --- Documentation/s390/kvm.txt | 125 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 Documentation/s390/kvm.txt (limited to 'Documentation') diff --git a/Documentation/s390/kvm.txt b/Documentation/s390/kvm.txt new file mode 100644 index 000000000000..6f5ceb0f09fc --- /dev/null +++ b/Documentation/s390/kvm.txt @@ -0,0 +1,125 @@ +*** BIG FAT WARNING *** +The kvm module is currently in EXPERIMENTAL state for s390. This means that +the interface to the module is not yet considered to remain stable. Thus, be +prepared that we keep breaking your userspace application and guest +compatibility over and over again until we feel happy with the result. Make sure +your guest kernel, your host kernel, and your userspace launcher are in a +consistent state. + +This Documentation describes the unique ioctl calls to /dev/kvm, the resulting +kvm-vm file descriptors, and the kvm-vcpu file descriptors that differ from x86. + +1. ioctl calls to /dev/kvm +KVM does support the following ioctls on s390 that are common with other +architectures and do behave the same: +KVM_GET_API_VERSION +KVM_CREATE_VM (*) see note +KVM_CHECK_EXTENSION +KVM_GET_VCPU_MMAP_SIZE + +Notes: +* KVM_CREATE_VM may fail on s390, if the calling process has multiple +threads and has not called KVM_S390_ENABLE_SIE before. + +In addition, on s390 the following architecture specific ioctls are supported: +ioctl: KVM_S390_ENABLE_SIE +args: none +see also: include/linux/kvm.h +This call causes the kernel to switch on PGSTE in the user page table. This +operation is needed in order to run a virtual machine, and it requires the +calling process to be single-threaded. Note that the first call to KVM_CREATE_VM +will implicitly try to switch on PGSTE if the user process has not called +KVM_S390_ENABLE_SIE before. User processes that want to launch multiple threads +before creating a virtual machine have to call KVM_S390_ENABLE_SIE, or will +observe an error calling KVM_CREATE_VM. Switching on PGSTE is a one-time +operation, is not reversible, and will persist over the entire lifetime of +the calling process. It does not have any user-visible effect other than a small +performance penalty. + +2. ioctl calls to the kvm-vm file descriptor +KVM does support the following ioctls on s390 that are common with other +architectures and do behave the same: +KVM_CREATE_VCPU +KVM_SET_USER_MEMORY_REGION (*) see note +KVM_GET_DIRTY_LOG (**) see note + +Notes: +* kvm does only allow exactly one memory slot on s390, which has to start + at guest absolute address zero and at a user address that is aligned on any + page boundary. This hardware "limitation" allows us to have a few unique + optimizations. The memory slot doesn't have to be filled + with memory actually, it may contain sparse holes. That said, with different + user memory layout this does still allow a large flexibility when + doing the guest memory setup. +** KVM_GET_DIRTY_LOG doesn't work properly yet. The user will receive an empty +log. This ioctl call is only needed for guest migration, and we intend to +implement this one in the future. + +In addition, on s390 the following architecture specific ioctls for the kvm-vm +file descriptor are supported: +ioctl: KVM_S390_INTERRUPT +args: struct kvm_s390_interrupt * +see also: include/linux/kvm.h +This ioctl is used to submit a floating interrupt for a virtual machine. +Floating interrupts may be delivered to any virtual cpu in the configuration. +Only some interrupt types defined in include/linux/kvm.h make sense when +submitted as floating interrupts. The following interrupts are not considered +to be useful as floating interrupts, and a call to inject them will result in +-EINVAL error code: program interrupts and interprocessor signals. Valid +floating interrupts are: +KVM_S390_INT_VIRTIO +KVM_S390_INT_SERVICE + +3. ioctl calls to the kvm-vcpu file descriptor +KVM does support the following ioctls on s390 that are common with other +architectures and do behave the same: +KVM_RUN +KVM_GET_REGS +KVM_SET_REGS +KVM_GET_SREGS +KVM_SET_SREGS +KVM_GET_FPU +KVM_SET_FPU + +In addition, on s390 the following architecture specific ioctls for the +kvm-vcpu file descriptor are supported: +ioctl: KVM_S390_INTERRUPT +args: struct kvm_s390_interrupt * +see also: include/linux/kvm.h +This ioctl is used to submit an interrupt for a specific virtual cpu. +Only some interrupt types defined in include/linux/kvm.h make sense when +submitted for a specific cpu. The following interrupts are not considered +to be useful, and a call to inject them will result in -EINVAL error code: +service processor calls and virtio interrupts. Valid interrupt types are: +KVM_S390_PROGRAM_INT +KVM_S390_SIGP_STOP +KVM_S390_RESTART +KVM_S390_SIGP_SET_PREFIX +KVM_S390_INT_EMERGENCY + +ioctl: KVM_S390_STORE_STATUS +args: unsigned long +see also: include/linux/kvm.h +This ioctl stores the state of the cpu at the guest real address given as +argument, unless one of the following values defined in include/linux/kvm.h +is given as arguement: +KVM_S390_STORE_STATUS_NOADDR - the CPU stores its status to the save area in +absolute lowcore as defined by the principles of operation +KVM_S390_STORE_STATUS_PREFIXED - the CPU stores its status to the save area in +its prefix page just like the dump tool that comes with zipl. This is useful +to create a system dump for use with lkcdutils or crash. + +ioctl: KVM_S390_SET_INITIAL_PSW +args: struct kvm_s390_psw * +see also: include/linux/kvm.h +This ioctl can be used to set the processor status word (psw) of a stopped cpu +prior to running it with KVM_RUN. Note that this call is not required to modify +the psw during sie intercepts that fall back to userspace because struct kvm_run +does contain the psw, and this value is evaluated during reentry of KVM_RUN +after the intercept exit was recognized. + +ioctl: KVM_S390_INITIAL_RESET +args: none +see also: include/linux/kvm.h +This ioctl can be used to perform an initial cpu reset as defined by the +principles of operation. The target cpu has to be in stopped state. -- cgit v1.2.3 From fdae862f91728aec6dd8fd62cd2398868c906b6b Mon Sep 17 00:00:00 2001 From: Xiantao Zhang Date: Tue, 1 Apr 2008 15:08:29 +0800 Subject: KVM: ia64: Add a guide about how to create kvm guests on ia64 Guide for creating virtual machine on kvm/ia64. Signed-off-by: Xiantao Zhang Signed-off-by: Avi Kivity --- Documentation/ia64/kvm.txt | 82 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 Documentation/ia64/kvm.txt (limited to 'Documentation') diff --git a/Documentation/ia64/kvm.txt b/Documentation/ia64/kvm.txt new file mode 100644 index 000000000000..bec9d815da33 --- /dev/null +++ b/Documentation/ia64/kvm.txt @@ -0,0 +1,82 @@ +Currently, kvm module in EXPERIMENTAL stage on IA64. This means that +interfaces are not stable enough to use. So, plase had better don't run +critical applications in virtual machine. We will try our best to make it +strong in future versions! + Guide: How to boot up guests on kvm/ia64 + +This guide is to describe how to enable kvm support for IA-64 systems. + +1. Get the kvm source from git.kernel.org. + Userspace source: + git clone git://git.kernel.org/pub/scm/virt/kvm/kvm-userspace.git + Kernel Source: + git clone git://git.kernel.org/pub/scm/linux/kernel/git/xiantao/kvm-ia64.git + +2. Compile the source code. + 2.1 Compile userspace code: + (1)cd ./kvm-userspace + (2)./configure + (3)cd kernel + (4)make sync LINUX= $kernel_dir (kernel_dir is the directory of kernel source.) + (5)cd .. + (6)make qemu + (7)cd qemu; make install + + 2.2 Compile kernel source code: + (1) cd ./$kernel_dir + (2) Make menuconfig + (3) Enter into virtualization option, and choose kvm. + (4) make + (5) Once (4) done, make modules_install + (6) Make initrd, and use new kernel to reboot up host machine. + (7) Once (6) done, cd $kernel_dir/arch/ia64/kvm + (8) insmod kvm.ko; insmod kvm-intel.ko + +Note: For step 2, please make sure that host page size == TARGET_PAGE_SIZE of qemu, otherwise, may fail. + +3. Get Guest Firmware named as Flash.fd, and put it under right place: + (1) If you have the guest firmware (binary) released by Intel Corp for Xen, use it directly. + + (2) If you have no firmware at hand, Please download its source from + hg clone http://xenbits.xensource.com/ext/efi-vfirmware.hg + you can get the firmware's binary in the directory of efi-vfirmware.hg/binaries. + + (3) Rename the firware you owned to Flash.fd, and copy it to /usr/local/share/qemu + +4. Boot up Linux or Windows guests: + 4.1 Create or install a image for guest boot. If you have xen experience, it should be easy. + + 4.2 Boot up guests use the following command. + /usr/local/bin/qemu-system-ia64 -smp xx -m 512 -hda $your_image + (xx is the number of virtual processors for the guest, now the maximum value is 4) + +5. Known possibile issue on some platforms with old Firmware. + +If meet strange host crashe issues, try to solve it through either of the following ways: + +(1): Upgrade your Firmware to the latest one. + +(2): Applying the below patch to kernel source. +diff --git a/arch/ia64/kernel/pal.S b/arch/ia64/kernel/pal.S +index 0b53344..f02b0f7 100644 +--- a/arch/ia64/kernel/pal.S ++++ b/arch/ia64/kernel/pal.S +@@ -84,7 +84,8 @@ GLOBAL_ENTRY(ia64_pal_call_static) + mov ar.pfs = loc1 + mov rp = loc0 + ;; +- srlz.d // seralize restoration of psr.l ++ srlz.i // seralize restoration of psr.l ++ ;; + br.ret.sptk.many b0 + END(ia64_pal_call_static) + +6. Bug report: + If you found any issues when use kvm/ia64, Please post the bug info to kvm-ia64-devel mailing list. + https://lists.sourceforge.net/lists/listinfo/kvm-ia64-devel/ + +Thanks for your interest! Let's work together, and make kvm/ia64 stronger and stronger! + + + Xiantao Zhang + 2008.3.10 -- cgit v1.2.3 From 258ac8e066622df3fef94c8adf32596faae5ab71 Mon Sep 17 00:00:00 2001 From: Avi Kivity Date: Sun, 6 Apr 2008 14:25:46 +0300 Subject: KVM: Register ioctl range Signed-off-by: Avi Kivity --- Documentation/ioctl-number.txt | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Documentation') diff --git a/Documentation/ioctl-number.txt b/Documentation/ioctl-number.txt index c18363bd8d11..240ce7a56c40 100644 --- a/Documentation/ioctl-number.txt +++ b/Documentation/ioctl-number.txt @@ -183,6 +183,8 @@ Code Seq# Include File Comments 0xAC 00-1F linux/raw.h 0xAD 00 Netfilter device in development: +0xAE all linux/kvm.h Kernel-based Virtual Machine + 0xB0 all RATIO devices in development: 0xB1 00-1F PPPoX -- cgit v1.2.3 From 9fd91d959f1a19d1bfa46d97cbbbb55641ce26a6 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:23 +0200 Subject: ide: add "ignore_cable" parameter (take 2) Add "ignore_cable" parameter: * "ide_core.ignore_cable=[interface_number]" boot option if IDE is built-in (i.e. "ide_core.ignore_cable=1" to force ignoring cable for "ide1") * "ignore_cable=[interface_number]" module parameter (for ide_core module) if IDE is compiled as module v2: * Add ide_port_apply_params() helper - use it in ide_device_add_all() and ide_scan_port(). * Make it possible to later disable ignoring cable detection by passing "[interface_number]:0" to /sys/module/ide_core/parameters/ignore_cable (however sysfs interface is not enabled yet since it needs some other IDE changes to make it work reliable). Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 15 ++++++++++----- drivers/ide/ide-probe.c | 10 +++++++++- drivers/ide/ide.c | 32 ++++++++++++++++++++++++++++++++ include/linux/ide.h | 2 ++ 4 files changed, 53 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 486c699f4aea..829a618c3e93 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -224,11 +224,6 @@ Summary of ide driver parameters for kernel command line "idex=reset" : reset interface after probe - "idex=ata66" : informs the interface that it has an 80c cable - for chipsets that are ATA-66 capable, but the - ability to bit test for detection is currently - unknown. - "ide=doubler" : probe/support IDE doublers on Amiga There may be more options than shown -- use the source, Luke! @@ -251,6 +246,16 @@ are detected automatically). You also need to use "probe" kernel parameter for ide-4drives driver (support for IDE generic chipset with four drives on one port). +To force ignoring cable detection (this should be needed only if you're using +short 40-wires cable which cannot be automatically detected - if this is not +a case please report it as a bug instead) use "ignore_cable" kernel parameter: + +* "ide_core.ignore_cable=[interface_number]" boot option if IDE is built-in + (i.e. "ide_core.ignore_cable=1" to force ignoring cable for "ide1") + +* "ignore_cable=[interface_number]" module parameter (for ide_core module) + if IDE is compiled as module + ================================================================================ Some Terminology diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index a4b65b321f51..4a33100a2314 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -1518,13 +1518,20 @@ int ide_device_add_all(u8 *idx, const struct ide_port_info *d) int i, rc = 0; for (i = 0; i < MAX_HWIFS; i++) { - if (d == NULL || idx[i] == 0xff) { + if (idx[i] == 0xff) { mate = NULL; continue; } hwif = &ide_hwifs[idx[i]]; + ide_port_apply_params(hwif); + + if (d == NULL) { + mate = NULL; + continue; + } + if (d->chipset != ide_etrax100 && (i & 1) && mate) { hwif->mate = mate; mate->mate = hwif; @@ -1621,6 +1628,7 @@ EXPORT_SYMBOL_GPL(ide_device_add); void ide_port_scan(ide_hwif_t *hwif) { + ide_port_apply_params(hwif); ide_port_cable_detect(hwif); ide_port_init_devices(hwif); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index bced02f9f2c3..6cd112cc4af3 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -1239,6 +1239,38 @@ static void ide_port_class_release(struct device *portdev) put_device(&hwif->gendev); } +static unsigned int ide_ignore_cable; + +static int ide_set_ignore_cable(const char *s, struct kernel_param *kp) +{ + int i, j = 1; + + if (sscanf(s, "%d:%d", &i, &j) != 2 && sscanf(s, "%d", &i) != 1) + return -EINVAL; + + if (i >= MAX_HWIFS || j < 0 || j > 1) + return -EINVAL; + + if (j) + ide_ignore_cable |= (1 << i); + else + ide_ignore_cable &= (1 << i); + + return 0; +} + +module_param_call(ignore_cable, ide_set_ignore_cable, NULL, NULL, 0); +MODULE_PARM_DESC(ignore_cable, "ignore cable detection"); + +void ide_port_apply_params(ide_hwif_t *hwif) +{ + if (ide_ignore_cable & (1 << hwif->index)) { + printk(KERN_INFO "ide: ignoring cable detection for %s\n", + hwif->name); + hwif->cbl = ATA_CBL_PATA40_SHORT; + } +} + /* * This is gets invoked once during initialization, to set *everything* up */ diff --git a/include/linux/ide.h b/include/linux/ide.h index f0af504dfa42..f80d303e5dcd 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -1222,6 +1222,8 @@ void ide_unregister_region(struct gendisk *); void ide_undecoded_slave(ide_drive_t *); +void ide_port_apply_params(ide_hwif_t *); + int ide_device_add_all(u8 *idx, const struct ide_port_info *); int ide_device_add(u8 idx[4], const struct ide_port_info *); int ide_legacy_device_add(const struct ide_port_info *, unsigned long); -- cgit v1.2.3 From 9dd4cf1fb949f6ba56b67078c09ef1b78f3c9421 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:24 +0200 Subject: ide: remove obsoleted "idex=serialize" kernel parameter Remove obsoleted "idex=serialize" kernel parameter (it has been obsoleted since 1 Nov 2004). Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 5 ----- drivers/ide/ide.c | 9 ++------- 2 files changed, 2 insertions(+), 12 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 829a618c3e93..8209033d2a7f 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -217,11 +217,6 @@ Summary of ide driver parameters for kernel command line As for VLB, it is safest to not specify it. Bigger values are safer than smaller ones. - "idex=serialize" : do not overlap operations on idex. Please note - that you will have to specify this option for - both the respective primary and secondary channel - to take effect. - "idex=reset" : reset interface after probe "ide=doubler" : probe/support IDE doublers on Amiga diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 6cd112cc4af3..3cac96f3b0aa 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -995,7 +995,7 @@ static int __init ide_setup(char *s) * (-8, -9, -10) are reserved to ease the hardcoding. */ static const char *ide_words[] = { - "minus1", "serialize", "minus3", "minus4", + "minus1", "minus2", "minus3", "minus4", "reset", "minus6", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", NULL }; @@ -1076,12 +1076,7 @@ static int __init ide_setup(char *s) case -5: /* "reset" */ hwif->reset = 1; goto obsolete_option; - case -2: /* "serialize" */ - hwif->mate = &ide_hwifs[hw^1]; - hwif->mate->mate = hwif; - hwif->serialized = hwif->mate->serialized = 1; - goto obsolete_option; - + case -2: case -1: case 0: case 1: -- cgit v1.2.3 From e460a59751a7e53b549c63d4d308ba73582c8def Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:24 +0200 Subject: ide: remove obsoleted "idex=reset" kernel parameter Remove obsoleted "idex=reset" kernel parameter (it has been obsoleted since 1 Nov 2004). Then remove corresponding code from ide_probe_port() and no longer used ->reset field from ide_hwif_t. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 2 -- drivers/ide/ide-probe.c | 9 ++------- drivers/ide/ide.c | 6 ++---- include/linux/ide.h | 1 - 4 files changed, 4 insertions(+), 14 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 8209033d2a7f..53e5beda525c 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -217,8 +217,6 @@ Summary of ide driver parameters for kernel command line As for VLB, it is safest to not specify it. Bigger values are safer than smaller ones. - "idex=reset" : reset interface after probe - "ide=doubler" : probe/support IDE doublers on Amiga There may be more options than shown -- use the source, Luke! diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 4a33100a2314..004062b5751e 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -800,14 +800,9 @@ static int ide_probe_port(ide_hwif_t *hwif) if (drive->present) rc = 0; } - if (hwif->io_ports[IDE_CONTROL_OFFSET] && hwif->reset) { - printk(KERN_WARNING "%s: reset\n", hwif->name); - hwif->OUTB(12, hwif->io_ports[IDE_CONTROL_OFFSET]); - udelay(10); - hwif->OUTB(8, hwif->io_ports[IDE_CONTROL_OFFSET]); - (void)ide_busy_sleep(hwif); - } + local_irq_restore(flags); + /* * Use cached IRQ number. It might be (and is...) changed by probe * code above diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 3cac96f3b0aa..7ccf99a11fb6 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -996,7 +996,7 @@ static int __init ide_setup(char *s) */ static const char *ide_words[] = { "minus1", "minus2", "minus3", "minus4", - "reset", "minus6", "ata66", "minus8", "minus9", + "minus5", "minus6", "ata66", "minus8", "minus9", "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", "dtc2278", "umc8672", "ali14xx", NULL }; @@ -1073,9 +1073,7 @@ static int __init ide_setup(char *s) #else goto bad_hwif; #endif - case -5: /* "reset" */ - hwif->reset = 1; - goto obsolete_option; + case -5: case -2: case -1: case 0: diff --git a/include/linux/ide.h b/include/linux/ide.h index f80d303e5dcd..5f8df20a9e39 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -520,7 +520,6 @@ typedef struct hwif_s { unsigned present : 1; /* this interface exists */ unsigned serialized : 1; /* serialized all channel operation */ unsigned sharing_irq: 1; /* 1 = sharing irq with another hwif */ - unsigned reset : 1; /* reset after probe */ unsigned sg_mapped : 1; /* sg_table and sg_nents are ready */ unsigned mmio : 1; /* host uses MMIO */ -- cgit v1.2.3 From ef87f8d09639cbe22201c7dfe07586c43b255108 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:24 +0200 Subject: ide: remove obsoleted "idex=" kernel parameters * Remove obsoleted "idex=" kernel parameters. * Make probe_* and cmd640_vlb variables static. Cc: Andrew Morton Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 2 - Documentation/kernel-parameters.txt | 4 -- drivers/ide/ide.c | 115 +----------------------------------- drivers/ide/legacy/ali14xx.c | 2 +- drivers/ide/legacy/dtc2278.c | 2 +- drivers/ide/legacy/ht6560b.c | 2 +- drivers/ide/legacy/ide-4drives.c | 2 +- drivers/ide/legacy/qd65xx.c | 2 +- drivers/ide/legacy/umc8672.c | 2 +- drivers/ide/pci/cmd640.c | 5 +- 10 files changed, 8 insertions(+), 130 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 53e5beda525c..af95fb33d1a1 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -186,8 +186,6 @@ Summary of ide driver parameters for kernel command line "hdx=" is recognized for all "x" from "a" to "u", such as "hdc". - "idex=" is recognized for all "x" from "0" to "9", such as "ide1". - "hdx=noprobe" : drive may be present, but do not probe for it "hdx=none" : drive is NOT present, ignore cmos and do not probe diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt index bf6303ec0bde..e5f3d918316f 100644 --- a/Documentation/kernel-parameters.txt +++ b/Documentation/kernel-parameters.txt @@ -772,10 +772,6 @@ and is between 256 and 4096 characters. It is defined in the file Format: ide=nodma or ide=doubler See Documentation/ide/ide.txt. - ide?= [HW] (E)IDE subsystem - Format: ide?=ata66 or chipset specific parameters. - See Documentation/ide/ide.txt. - idebus= [HW] (E)IDE subsystem - VLB/PCI bus speed See Documentation/ide/ide.txt. diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 7ccf99a11fb6..a33840d11770 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -837,16 +837,6 @@ static int __init match_parm (char *s, const char *keywords[], int vals[], int m return 0; /* zero = nothing matched */ } -extern int probe_ali14xx; -extern int probe_umc8672; -extern int probe_dtc2278; -extern int probe_ht6560b; -extern int probe_qd65xx; -extern int cmd640_vlb; -extern int probe_4drives; - -static int __initdata is_chipset_set; - /* * ide_setup() gets called VERY EARLY during initialization, * to handle kernel "command line" strings beginning with "hdx=" or "ide". @@ -855,14 +845,12 @@ static int __initdata is_chipset_set; */ static int __init ide_setup(char *s) { - int i, vals[3]; ide_hwif_t *hwif; ide_drive_t *drive; unsigned int hw, unit; + int vals[3]; const char max_drive = 'a' + ((MAX_HWIFS * MAX_DRIVES) - 1); - const char max_hwif = '0' + (MAX_HWIFS - 1); - if (strncmp(s,"hd",2) == 0 && s[2] == '=') /* hd= is for hd.c */ return 0; /* driver and not us */ @@ -986,114 +974,13 @@ static int __init ide_setup(char *s) printk(" -- BAD BUS SPEED! Expected value from 20 to 66"); goto done; } - /* - * Look for interface options: "idex=" - */ - if (s[3] >= '0' && s[3] <= max_hwif) { - /* - * Be VERY CAREFUL changing this: note hardcoded indexes below - * (-8, -9, -10) are reserved to ease the hardcoding. - */ - static const char *ide_words[] = { - "minus1", "minus2", "minus3", "minus4", - "minus5", "minus6", "ata66", "minus8", "minus9", - "minus10", "four", "qd65xx", "ht6560b", "cmd640_vlb", - "dtc2278", "umc8672", "ali14xx", NULL }; - - hw = s[3] - '0'; - hwif = &ide_hwifs[hw]; - i = match_parm(&s[4], ide_words, vals, 3); - - /* - * Cryptic check to ensure chipset not already set for hwif. - * Note: we can't depend on hwif->chipset here. - */ - if (i >= -18 && i <= -11) { - /* chipset already specified */ - if (is_chipset_set) - goto bad_option; - /* these drivers are for "ide0=" only */ - if (hw != 0) - goto bad_hwif; - is_chipset_set = 1; - printk("\n"); - } - switch (i) { -#ifdef CONFIG_BLK_DEV_ALI14XX - case -17: /* "ali14xx" */ - probe_ali14xx = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_UMC8672 - case -16: /* "umc8672" */ - probe_umc8672 = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_DTC2278 - case -15: /* "dtc2278" */ - probe_dtc2278 = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_CMD640 - case -14: /* "cmd640_vlb" */ - cmd640_vlb = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_HT6560B - case -13: /* "ht6560b" */ - probe_ht6560b = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_QD65XX - case -12: /* "qd65xx" */ - probe_qd65xx = 1; - goto obsolete_option; -#endif -#ifdef CONFIG_BLK_DEV_4DRIVES - case -11: /* "four" drives on one set of ports */ - probe_4drives = 1; - goto obsolete_option; -#endif - case -10: /* minus10 */ - case -9: /* minus9 */ - case -8: /* minus8 */ - case -6: - case -4: - case -3: - goto bad_option; - case -7: /* ata66 */ -#ifdef CONFIG_BLK_DEV_IDEPCI - /* - * Use ATA_CBL_PATA40_SHORT so drive side - * cable detection is also overriden. - */ - hwif->cbl = ATA_CBL_PATA40_SHORT; - goto obsolete_option; -#else - goto bad_hwif; -#endif - case -5: - case -2: - case -1: - case 0: - case 1: - case 2: - case 3: - goto bad_option; - default: - printk(" -- SUPPORT NOT CONFIGURED IN THIS KERNEL\n"); - return 1; - } - } bad_option: printk(" -- BAD OPTION\n"); return 1; obsolete_option: printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n"); return 1; -bad_hwif: - printk("-- NOT SUPPORTED ON ide%d", hw); done: printk("\n"); return 1; diff --git a/drivers/ide/legacy/ali14xx.c b/drivers/ide/legacy/ali14xx.c index 6efbf947c6db..c6898639b799 100644 --- a/drivers/ide/legacy/ali14xx.c +++ b/drivers/ide/legacy/ali14xx.c @@ -220,7 +220,7 @@ static int __init ali14xx_probe(void) return ide_legacy_device_add(&ali14xx_port_info, 0); } -int probe_ali14xx; +static int probe_ali14xx; module_param_named(probe, probe_ali14xx, bool, 0); MODULE_PARM_DESC(probe, "probe for ALI M14xx chipsets"); diff --git a/drivers/ide/legacy/dtc2278.c b/drivers/ide/legacy/dtc2278.c index f7c4ad1c57c0..581909ac1032 100644 --- a/drivers/ide/legacy/dtc2278.c +++ b/drivers/ide/legacy/dtc2278.c @@ -131,7 +131,7 @@ static int __init dtc2278_probe(void) return ide_legacy_device_add(&dtc2278_port_info, 0); } -int probe_dtc2278 = 0; +static int probe_dtc2278; module_param_named(probe, probe_dtc2278, bool, 0); MODULE_PARM_DESC(probe, "probe for DTC2278xx chipsets"); diff --git a/drivers/ide/legacy/ht6560b.c b/drivers/ide/legacy/ht6560b.c index 702d8deb5780..8b2a5b484d9f 100644 --- a/drivers/ide/legacy/ht6560b.c +++ b/drivers/ide/legacy/ht6560b.c @@ -323,7 +323,7 @@ static void __init ht6560b_port_init_devs(ide_hwif_t *hwif) hwif->drives[1].drive_data = t; } -int probe_ht6560b = 0; +static int probe_ht6560b; module_param_named(probe, probe_ht6560b, bool, 0); MODULE_PARM_DESC(probe, "probe for HT6560B chipset"); diff --git a/drivers/ide/legacy/ide-4drives.c b/drivers/ide/legacy/ide-4drives.c index 17f94d0cb539..ecae916a3385 100644 --- a/drivers/ide/legacy/ide-4drives.c +++ b/drivers/ide/legacy/ide-4drives.c @@ -6,7 +6,7 @@ #define DRV_NAME "ide-4drives" -int probe_4drives; +static int probe_4drives; module_param_named(probe, probe_4drives, bool, 0); MODULE_PARM_DESC(probe, "probe for generic IDE chipset with 4 drives/port"); diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 15a99aae0cf9..61d5889834e4 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -399,7 +399,7 @@ static int __init qd_probe(int base) return rc; } -int probe_qd65xx = 0; +static int probe_qd65xx; module_param_named(probe, probe_qd65xx, bool, 0); MODULE_PARM_DESC(probe, "probe for QD65xx chipsets"); diff --git a/drivers/ide/legacy/umc8672.c b/drivers/ide/legacy/umc8672.c index 17d515329fe0..6f25f0f4da09 100644 --- a/drivers/ide/legacy/umc8672.c +++ b/drivers/ide/legacy/umc8672.c @@ -158,7 +158,7 @@ static int __init umc8672_probe(void) return ide_legacy_device_add(&umc8672_port_info, 0); } -int probe_umc8672; +static int probe_umc8672; module_param_named(probe, probe_umc8672, bool, 0); MODULE_PARM_DESC(probe, "probe for UMC8672 chipset"); diff --git a/drivers/ide/pci/cmd640.c b/drivers/ide/pci/cmd640.c index 25c2f1bd175f..0f6f11e69807 100644 --- a/drivers/ide/pci/cmd640.c +++ b/drivers/ide/pci/cmd640.c @@ -111,10 +111,7 @@ #define DRV_NAME "cmd640" -/* - * This flag is set in ide.c by the parameter: ide0=cmd640_vlb - */ -int cmd640_vlb; +static int cmd640_vlb; /* * CMD640 specific registers definition. -- cgit v1.2.3 From 4735f22cc10127189a13ce9b1c16fa152a99aaba Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 27 Apr 2008 15:38:28 +0200 Subject: ide-tape: remove pipelined mode description from Documentation/ide/ide-tape.txt Signed-off-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide-tape.txt | 79 ------------------------------------------ 1 file changed, 79 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide-tape.txt b/Documentation/ide/ide-tape.txt index 658f271a373f..51f596b282cd 100644 --- a/Documentation/ide/ide-tape.txt +++ b/Documentation/ide/ide-tape.txt @@ -8,8 +8,6 @@ * interface, on the other hand, creates new requests, adds them * to the request-list of the block device, and waits for their completion. * - * Pipelined operation mode is now supported on both reads and writes. - * * The block device major and minor numbers are determined from the * tape's relative position in the ide interfaces, as explained in ide.c. * @@ -45,83 +43,6 @@ * * | Special care is recommended. Have Fun! * - * - * An overview of the pipelined operation mode. - * - * In the pipelined write mode, we will usually just add requests to our - * pipeline and return immediately, before we even start to service them. The - * user program will then have enough time to prepare the next request while - * we are still busy servicing previous requests. In the pipelined read mode, - * the situation is similar - we add read-ahead requests into the pipeline, - * before the user even requested them. - * - * The pipeline can be viewed as a "safety net" which will be activated when - * the system load is high and prevents the user backup program from keeping up - * with the current tape speed. At this point, the pipeline will get - * shorter and shorter but the tape will still be streaming at the same speed. - * Assuming we have enough pipeline stages, the system load will hopefully - * decrease before the pipeline is completely empty, and the backup program - * will be able to "catch up" and refill the pipeline again. - * - * When using the pipelined mode, it would be best to disable any type of - * buffering done by the user program, as ide-tape already provides all the - * benefits in the kernel, where it can be done in a more efficient way. - * As we will usually not block the user program on a request, the most - * efficient user code will then be a simple read-write-read-... cycle. - * Any additional logic will usually just slow down the backup process. - * - * Using the pipelined mode, I get a constant over 400 KBps throughput, - * which seems to be the maximum throughput supported by my tape. - * - * However, there are some downfalls: - * - * 1. We use memory (for data buffers) in proportional to the number - * of pipeline stages (each stage is about 26 KB with my tape). - * 2. In the pipelined write mode, we cheat and postpone error codes - * to the user task. In read mode, the actual tape position - * will be a bit further than the last requested block. - * - * Concerning (1): - * - * 1. We allocate stages dynamically only when we need them. When - * we don't need them, we don't consume additional memory. In - * case we can't allocate stages, we just manage without them - * (at the expense of decreased throughput) so when Linux is - * tight in memory, we will not pose additional difficulties. - * - * 2. The maximum number of stages (which is, in fact, the maximum - * amount of memory) which we allocate is limited by the compile - * time parameter IDETAPE_MAX_PIPELINE_STAGES. - * - * 3. The maximum number of stages is a controlled parameter - We - * don't start from the user defined maximum number of stages - * but from the lower IDETAPE_MIN_PIPELINE_STAGES (again, we - * will not even allocate this amount of stages if the user - * program can't handle the speed). We then implement a feedback - * loop which checks if the pipeline is empty, and if it is, we - * increase the maximum number of stages as necessary until we - * reach the optimum value which just manages to keep the tape - * busy with minimum allocated memory or until we reach - * IDETAPE_MAX_PIPELINE_STAGES. - * - * Concerning (2): - * - * In pipelined write mode, ide-tape can not return accurate error codes - * to the user program since we usually just add the request to the - * pipeline without waiting for it to be serviced. In case an error - * occurs, I will report it on the next user request. - * - * In the pipelined read mode, subsequent read requests or forward - * filemark spacing will perform correctly, as we preserve all blocks - * and filemarks which we encountered during our excess read-ahead. - * - * For accurate tape positioning and error reporting, disabling - * pipelined mode might be the best option. - * - * You can enable/disable/tune the pipelined operation mode by adjusting - * the compile time parameters below. - * - * * Possible improvements. * * 1. Support for the ATAPI overlap protocol. -- cgit v1.2.3 From 10569713c78f3c499745651aebc90b0d1c454c28 Mon Sep 17 00:00:00 2001 From: Borislav Petkov Date: Sun, 27 Apr 2008 15:38:28 +0200 Subject: ide-tape: remove comments markup from Documentation/ide/ide-tape.txt Signed-off-by: Borislav Petkov Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide-tape.txt | 132 ++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 67 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide-tape.txt b/Documentation/ide/ide-tape.txt index 51f596b282cd..3f348a0b21d8 100644 --- a/Documentation/ide/ide-tape.txt +++ b/Documentation/ide/ide-tape.txt @@ -1,67 +1,65 @@ -/* - * IDE ATAPI streaming tape driver. - * - * This driver is a part of the Linux ide driver. - * - * The driver, in co-operation with ide.c, basically traverses the - * request-list for the block device interface. The character device - * interface, on the other hand, creates new requests, adds them - * to the request-list of the block device, and waits for their completion. - * - * The block device major and minor numbers are determined from the - * tape's relative position in the ide interfaces, as explained in ide.c. - * - * The character device interface consists of the following devices: - * - * ht0 major 37, minor 0 first IDE tape, rewind on close. - * ht1 major 37, minor 1 second IDE tape, rewind on close. - * ... - * nht0 major 37, minor 128 first IDE tape, no rewind on close. - * nht1 major 37, minor 129 second IDE tape, no rewind on close. - * ... - * - * The general magnetic tape commands compatible interface, as defined by - * include/linux/mtio.h, is accessible through the character device. - * - * General ide driver configuration options, such as the interrupt-unmask - * flag, can be configured by issuing an ioctl to the block device interface, - * as any other ide device. - * - * Our own ide-tape ioctl's can be issued to either the block device or - * the character device interface. - * - * Maximal throughput with minimal bus load will usually be achieved in the - * following scenario: - * - * 1. ide-tape is operating in the pipelined operation mode. - * 2. No buffering is performed by the user backup program. - * - * Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive. - * - * Here are some words from the first releases of hd.c, which are quoted - * in ide.c and apply here as well: - * - * | Special care is recommended. Have Fun! - * - * Possible improvements. - * - * 1. Support for the ATAPI overlap protocol. - * - * In order to maximize bus throughput, we currently use the DSC - * overlap method which enables ide.c to service requests from the - * other device while the tape is busy executing a command. The - * DSC overlap method involves polling the tape's status register - * for the DSC bit, and servicing the other device while the tape - * isn't ready. - * - * In the current QIC development standard (December 1995), - * it is recommended that new tape drives will *in addition* - * implement the ATAPI overlap protocol, which is used for the - * same purpose - efficient use of the IDE bus, but is interrupt - * driven and thus has much less CPU overhead. - * - * ATAPI overlap is likely to be supported in most new ATAPI - * devices, including new ATAPI cdroms, and thus provides us - * a method by which we can achieve higher throughput when - * sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. - */ +IDE ATAPI streaming tape driver. + +This driver is a part of the Linux ide driver. + +The driver, in co-operation with ide.c, basically traverses the +request-list for the block device interface. The character device +interface, on the other hand, creates new requests, adds them +to the request-list of the block device, and waits for their completion. + +The block device major and minor numbers are determined from the +tape's relative position in the ide interfaces, as explained in ide.c. + +The character device interface consists of the following devices: + +ht0 major 37, minor 0 first IDE tape, rewind on close. +ht1 major 37, minor 1 second IDE tape, rewind on close. +... +nht0 major 37, minor 128 first IDE tape, no rewind on close. +nht1 major 37, minor 129 second IDE tape, no rewind on close. +... + +The general magnetic tape commands compatible interface, as defined by +include/linux/mtio.h, is accessible through the character device. + +General ide driver configuration options, such as the interrupt-unmask +flag, can be configured by issuing an ioctl to the block device interface, +as any other ide device. + +Our own ide-tape ioctl's can be issued to either the block device or +the character device interface. + +Maximal throughput with minimal bus load will usually be achieved in the +following scenario: + + 1. ide-tape is operating in the pipelined operation mode. + 2. No buffering is performed by the user backup program. + +Testing was done with a 2 GB CONNER CTMA 4000 IDE ATAPI Streaming Tape Drive. + +Here are some words from the first releases of hd.c, which are quoted +in ide.c and apply here as well: + +| Special care is recommended. Have Fun! + +Possible improvements: + +1. Support for the ATAPI overlap protocol. + +In order to maximize bus throughput, we currently use the DSC +overlap method which enables ide.c to service requests from the +other device while the tape is busy executing a command. The +DSC overlap method involves polling the tape's status register +for the DSC bit, and servicing the other device while the tape +isn't ready. + +In the current QIC development standard (December 1995), +it is recommended that new tape drives will *in addition* +implement the ATAPI overlap protocol, which is used for the +same purpose - efficient use of the IDE bus, but is interrupt +driven and thus has much less CPU overhead. + +ATAPI overlap is likely to be supported in most new ATAPI +devices, including new ATAPI cdroms, and thus provides us +a method by which we can achieve higher throughput when +sharing a (fast) ATA-2 disk with any (slow) new ATAPI device. -- cgit v1.2.3 From 73f1ad8670effa9849c3d42457fa2b58f139e013 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:29 +0200 Subject: ide: mark "idebus=" kernel parameter as obsoleted (take 2) We have "vlb|pci_clock=" parameters now. Acked-by: Sergei Shtylyov Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 10 ---------- drivers/ide/ide.c | 2 +- drivers/ide/legacy/qd65xx.c | 2 -- drivers/ide/pci/cy82c693.c | 2 -- drivers/ide/pci/opti621.c | 3 +-- 5 files changed, 2 insertions(+), 17 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index af95fb33d1a1..eb4d3b7a6214 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -205,16 +205,6 @@ Summary of ide driver parameters for kernel command line "hdx=nodma" : disallow DMA - "idebus=xx" : inform IDE driver of VESA/PCI bus speed in MHz, - where "xx" is between 20 and 66 inclusive, - used when tuning chipset PIO modes. - For PCI bus, 25 is correct for a P75 system, - 30 is correct for P90,P120,P180 systems, - and 33 is used for P100,P133,P166 systems. - If in doubt, use idebus=33 for PCI. - As for VLB, it is safest to not specify it. - Bigger values are safer than smaller ones. - "ide=doubler" : probe/support IDE doublers on Amiga There may be more options than shown -- use the source, Luke! diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 3d1fc5fdc2b2..ad34fe98a23c 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -969,7 +969,7 @@ static int __init ide_setup(char *s) idebus_parameter = vals[0]; } else printk(" -- BAD BUS SPEED! Expected value from 20 to 66"); - goto done; + goto obsolete_option; } bad_option: diff --git a/drivers/ide/legacy/qd65xx.c b/drivers/ide/legacy/qd65xx.c index 5621963f755f..87cef68e8add 100644 --- a/drivers/ide/legacy/qd65xx.c +++ b/drivers/ide/legacy/qd65xx.c @@ -11,8 +11,6 @@ * * QDI QD6500/QD6580 EIDE controller fast support * - * Please set local bus speed using kernel parameter idebus - * for example, "idebus=33" stands for 33Mhz VLbus * To activate controller support, use "ide0=qd65xx" * To enable tuning, use "hda=autotune hdb=autotune" * To enable 2nd channel tuning (qd6580 only), use "hdc=autotune hdd=autotune" diff --git a/drivers/ide/pci/cy82c693.c b/drivers/ide/pci/cy82c693.c index 8ef551ab9571..77cc22c2ad45 100644 --- a/drivers/ide/pci/cy82c693.c +++ b/drivers/ide/pci/cy82c693.c @@ -18,8 +18,6 @@ * hdparm -t reports 8.17 MB/sec at about 6% CPU usage for the DTTA * - this is my first linux driver, so there's probably a lot of room * for optimizations and bug fixing, so feel free to do it. - * - use idebus=xx parameter to set PCI bus speed - needed to calc - * timings for PIO modes (default will be 40) * - if using PIO mode it's a good idea to set the PIO mode and * 32-bit I/O support (if possible), e.g. hdparm -p2 -c1 /dev/hda * - I had some problems with my IBM DHEA with PIO modes < 2 diff --git a/drivers/ide/pci/opti621.c b/drivers/ide/pci/opti621.c index f766be9afaf9..684160d3cc0e 100644 --- a/drivers/ide/pci/opti621.c +++ b/drivers/ide/pci/opti621.c @@ -53,8 +53,7 @@ * If you then set the second drive to another PIO, the old value * (automatically selected) will be overrided by yours. * There is a 25/33MHz switch in configuration - * register, but driver is written for use at any frequency which get - * (use idebus=xx to select PCI bus speed). + * register, but driver is written for use at any frequency. * * Version 0.1, Nov 8, 1996 * by Jaromir Koutek, for 2.1.8. -- cgit v1.2.3 From 207daeaabb5396995ebac63415fab71476b64ca3 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:29 +0200 Subject: ide: remove obsoleted "hdx=autotune" kernel parameter * Remove obsoleted "hdx=autotune" kernel parameter (we always auto-tune PIO if possible nowadays). * Remove no longer needed ide_drive_t.autotune flag. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 7 ------- drivers/ide/ide-probe.c | 4 +--- drivers/ide/ide.c | 5 +---- include/linux/ide.h | 1 - 4 files changed, 2 insertions(+), 15 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index eb4d3b7a6214..601e79ecef03 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -196,13 +196,6 @@ Summary of ide driver parameters for kernel command line "hdx=cyl,head,sect" : disk drive is present, with specified geometry - "hdx=autotune" : driver will attempt to tune interface speed - to the fastest PIO mode supported, - if possible for this drive only. - Not fully supported by all chipset types, - and quite likely to cause trouble with - older/odd IDE drives. - "hdx=nodma" : disallow DMA "ide=doubler" : probe/support IDE doublers on Amiga diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index 99972fe3e9e4..ace826f52811 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c @@ -827,8 +827,7 @@ static void ide_port_tune_devices(ide_hwif_t *hwif) ide_drive_t *drive = &hwif->drives[unit]; if (drive->present) { - if (drive->autotune) - ide_set_max_pio(drive); + ide_set_max_pio(drive); drive->nice1 = 1; @@ -1325,7 +1324,6 @@ static void ide_port_init_devices(ide_hwif_t *hwif) drive->unmask = 1; if (hwif->host_flags & IDE_HFLAG_NO_UNMASK_IRQS) drive->no_unmask = 1; - drive->autotune = 1; } if (port_ops && port_ops->port_init_devs) diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index ad34fe98a23c..71fa37979215 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -900,7 +900,7 @@ static int __init ide_setup(char *s) if (s[0] == 'h' && s[1] == 'd' && s[2] >= 'a' && s[2] <= max_drive) { const char *hd_words[] = { "none", "noprobe", "nowerr", "cdrom", "nodma", - "autotune", "-7", "-8", "-9", "-10", + "-6", "-7", "-8", "-9", "-10", "noflush", "remap", "remap63", "scsi", NULL }; unit = s[2] - 'a'; hw = unit / MAX_DRIVES; @@ -928,9 +928,6 @@ static int __init ide_setup(char *s) case -5: /* nodma */ drive->nodma = 1; goto done; - case -6: /* "autotune" */ - drive->autotune = 1; - goto obsolete_option; case -11: /* noflush */ drive->noflush = 1; goto done; diff --git a/include/linux/ide.h b/include/linux/ide.h index 0e7d44a6b94a..65dcbcfae162 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -321,7 +321,6 @@ typedef struct ide_drive_s { unsigned atapi_overlap : 1; /* ATAPI overlap (not supported) */ unsigned doorlocking : 1; /* for removable only: door lock/unlock works */ unsigned nodma : 1; /* disallow DMA */ - unsigned autotune : 1; /* 0=default, 1=autotune */ unsigned remap_0_to_1 : 1; /* 0=noremap, 1=remap 0->1 (for EZDrive) */ unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */ unsigned vdma : 1; /* 1=doing PIO over DMA 0=doing normal DMA */ -- cgit v1.2.3 From 6e87543a94fb2a966c81a61fc91246592f9719da Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:30 +0200 Subject: ide: add "nodma|noflush|noprobe|nowerr=" parameters * Add "nodma|noflush|noprobe|nowerr=" parameters. * Obsolete "hdx=noprobe|none|nowerr|nodma|noflush" kernel parameters. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 26 ++++++++-------- drivers/ide/ide.c | 79 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 88 insertions(+), 17 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 601e79ecef03..5bff93c89a23 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -99,10 +99,10 @@ with hd.c but not with ide.c), then an command line option may be specified for each drive for which you'd like the drive to skip the hardware probe/identification sequence. For example: - hdb=noprobe + ide_core.noprobe=0.1 or hdc=768,16,32 - hdc=noprobe + ide_core.noprobe=1.0 Note that when only one IDE device is attached to an interface, it should be jumpered as "single" or "master", *not* "slave". Many folks have had @@ -174,9 +174,7 @@ to /etc/modprobe.conf. When ide.c is used as a module, you can pass command line parameters to the driver using the "options=" keyword to insmod, while replacing any ',' with -';'. For example: - - insmod ide.o options="hda=nodma hdb=nodma" +';'. ================================================================================ @@ -186,18 +184,10 @@ Summary of ide driver parameters for kernel command line "hdx=" is recognized for all "x" from "a" to "u", such as "hdc". - "hdx=noprobe" : drive may be present, but do not probe for it - - "hdx=none" : drive is NOT present, ignore cmos and do not probe - - "hdx=nowerr" : ignore the WRERR_STAT bit on this drive - "hdx=cdrom" : drive is present, and is a cdrom drive "hdx=cyl,head,sect" : disk drive is present, with specified geometry - "hdx=nodma" : disallow DMA - "ide=doubler" : probe/support IDE doublers on Amiga There may be more options than shown -- use the source, Luke! @@ -230,6 +220,16 @@ a case please report it as a bug instead) use "ignore_cable" kernel parameter: * "ignore_cable=[interface_number]" module parameter (for ide_core module) if IDE is compiled as module +Other kernel parameters for ide_core are: + +* "nodma=[interface_number.device_number]" to disallow DMA for a device + +* "noflush=[interface_number.device_number]" to disable flush requests + +* "noprobe=[interface_number.device_number]" to skip probing + +* "nowerr=[interface_number.device_number]" to ignore the WRERR_STAT bit + ================================================================================ Some Terminology diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 71fa37979215..d8f40ee74ce8 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -915,10 +915,10 @@ static int __init ide_setup(char *s) case -1: /* "none" */ case -2: /* "noprobe" */ drive->noprobe = 1; - goto done; + goto obsolete_option; case -3: /* "nowerr" */ drive->bad_wstat = BAD_R_STAT; - goto done; + goto obsolete_option; case -4: /* "cdrom" */ drive->present = 1; drive->media = ide_cdrom; @@ -927,10 +927,10 @@ static int __init ide_setup(char *s) goto done; case -5: /* nodma */ drive->nodma = 1; - goto done; + goto obsolete_option; case -11: /* noflush */ drive->noflush = 1; - goto done; + goto obsolete_option; case -12: /* "remap" */ drive->remap_0_to_1 = 1; goto obsolete_option; @@ -1125,6 +1125,72 @@ EXPORT_SYMBOL_GPL(ide_pci_clk); module_param_named(pci_clock, ide_pci_clk, int, 0); MODULE_PARM_DESC(pci_clock, "PCI bus clock frequency (in MHz)"); +static int ide_set_dev_param_mask(const char *s, struct kernel_param *kp) +{ + int a, b, i, j = 1; + unsigned int *dev_param_mask = (unsigned int *)kp->arg; + + if (sscanf(s, "%d.%d:%d", &a, &b, &j) != 3 && + sscanf(s, "%d.%d", &a, &b) != 2) + return -EINVAL; + + i = a * MAX_DRIVES + b; + + if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1) + return -EINVAL; + + if (j) + *dev_param_mask |= (1 << i); + else + *dev_param_mask &= (1 << i); + + return 0; +} + +static unsigned int ide_nodma; + +module_param_call(nodma, ide_set_dev_param_mask, NULL, &ide_nodma, 0); +MODULE_PARM_DESC(nodma, "disallow DMA for a device"); + +static unsigned int ide_noflush; + +module_param_call(noflush, ide_set_dev_param_mask, NULL, &ide_noflush, 0); +MODULE_PARM_DESC(noflush, "disable flush requests for a device"); + +static unsigned int ide_noprobe; + +module_param_call(noprobe, ide_set_dev_param_mask, NULL, &ide_noprobe, 0); +MODULE_PARM_DESC(noprobe, "skip probing for a device"); + +static unsigned int ide_nowerr; + +module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); +MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device"); + +static void ide_dev_apply_params(ide_drive_t *drive) +{ + int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit; + + if (ide_nodma & (1 << i)) { + printk(KERN_INFO "ide: disallowing DMA for %s\n", drive->name); + drive->nodma = 1; + } + if (ide_noflush & (1 << i)) { + printk(KERN_INFO "ide: disabling flush requests for %s\n", + drive->name); + drive->noflush = 1; + } + if (ide_noprobe & (1 << i)) { + printk(KERN_INFO "ide: skipping probe for %s\n", drive->name); + drive->noprobe = 1; + } + if (ide_nowerr & (1 << i)) { + printk(KERN_INFO "ide: ignoring the WRERR_STAT bit for %s\n", + drive->name); + drive->bad_wstat = BAD_R_STAT; + } +} + static unsigned int ide_ignore_cable; static int ide_set_ignore_cable(const char *s, struct kernel_param *kp) @@ -1150,11 +1216,16 @@ MODULE_PARM_DESC(ignore_cable, "ignore cable detection"); void ide_port_apply_params(ide_hwif_t *hwif) { + int i; + if (ide_ignore_cable & (1 << hwif->index)) { printk(KERN_INFO "ide: ignoring cable detection for %s\n", hwif->name); hwif->cbl = ATA_CBL_PATA40_SHORT; } + + for (i = 0; i < MAX_DRIVES; i++) + ide_dev_apply_params(&hwif->drives[i]); } /* -- cgit v1.2.3 From 4706a7e03a03d6d206a93a49a0c723dd612cf8e9 Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:30 +0200 Subject: ide: add "cdrom=" and "chs=" parameters * Add "cdrom=" and "chs=" parameters. * Obsolete "hdx=cdrom" and "hdx=cyls,heads,sects" kernel parameters. Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 31 ++++++++++----------- drivers/ide/ide.c | 71 +++++++++++++++++++++++++++++++++++++++++++---- 2 files changed, 80 insertions(+), 22 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index 5bff93c89a23..caf24b21e7f5 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -82,17 +82,16 @@ Drives are normally found by auto-probing and/or examining the CMOS/BIOS data. For really weird situations, the apparent (fdisk) geometry can also be specified on the kernel "command line" using LILO. The format of such lines is: - hdx=cyls,heads,sects -or hdx=cdrom + ide_core.chs=[interface_number.device_number]:cyls,heads,sects +or ide_core.cdrom=[interface_number.device_number] -where hdx can be any of hda through hdh, Three values are required -(cyls,heads,sects). For example: +For example: - hdc=1050,32,64 hdd=cdrom + ide_core.chs=1.0:1050,32,64 ide_core.cdrom=1.1 -either {hda,hdb} or {hdc,hdd}. The results of successful auto-probing may -override the physical geometry/irq specified, though the "original" geometry -may be retained as the "logical" geometry for partitioning purposes (fdisk). +The results of successful auto-probing may override the physical geometry/irq +specified, though the "original" geometry may be retained as the "logical" +geometry for partitioning purposes (fdisk). If the auto-probing during boot time confuses a drive (ie. the drive works with hd.c but not with ide.c), then an command line option may be specified @@ -101,7 +100,7 @@ probe/identification sequence. For example: ide_core.noprobe=0.1 or - hdc=768,16,32 + ide_core.chs=1.0:768,16,32 ide_core.noprobe=1.0 Note that when only one IDE device is attached to an interface, it should be @@ -118,9 +117,9 @@ If for some reason your cdrom drive is *not* found at boot time, you can force the probe to look harder by supplying a kernel command line parameter via LILO, such as: - hdc=cdrom /* hdc = "master" on second interface */ + ide_core.cdrom=1.0 /* "master" on second interface (hdc) */ or - hdd=cdrom /* hdd = "slave" on second interface */ + ide_core.cdrom=1.1 /* "slave" on second interface (hdd) */ For example, a GW2000 system might have a hard drive on the primary interface (/dev/hda) and an IDE cdrom drive on the secondary interface @@ -182,12 +181,6 @@ driver using the "options=" keyword to insmod, while replacing any ',' with Summary of ide driver parameters for kernel command line -------------------------------------------------------- - "hdx=" is recognized for all "x" from "a" to "u", such as "hdc". - - "hdx=cdrom" : drive is present, and is a cdrom drive - - "hdx=cyl,head,sect" : disk drive is present, with specified geometry - "ide=doubler" : probe/support IDE doublers on Amiga There may be more options than shown -- use the source, Luke! @@ -230,6 +223,10 @@ Other kernel parameters for ide_core are: * "nowerr=[interface_number.device_number]" to ignore the WRERR_STAT bit +* "cdrom=[interface_number.device_number]" to force device as a CD-ROM + +* "chs=[interface_number.device_number]" to force device as a disk (using CHS) + ================================================================================ Some Terminology diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index d8f40ee74ce8..a4bceeecde70 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -924,7 +924,7 @@ static int __init ide_setup(char *s) drive->media = ide_cdrom; /* an ATAPI device ignores DRDY */ drive->ready_stat = 0; - goto done; + goto obsolete_option; case -5: /* nodma */ drive->nodma = 1; goto obsolete_option; @@ -948,7 +948,7 @@ static int __init ide_setup(char *s) drive->sect = drive->bios_sect = vals[2]; drive->present = 1; drive->forced_geom = 1; - goto done; + goto obsolete_option; default: goto bad_option; } @@ -975,9 +975,6 @@ bad_option: obsolete_option: printk(" -- OBSOLETE OPTION, WILL BE REMOVED SOON!\n"); return 1; -done: - printk("\n"); - return 1; } EXPORT_SYMBOL(ide_lock); @@ -1167,6 +1164,51 @@ static unsigned int ide_nowerr; module_param_call(nowerr, ide_set_dev_param_mask, NULL, &ide_nowerr, 0); MODULE_PARM_DESC(nowerr, "ignore the WRERR_STAT bit for a device"); +static unsigned int ide_cdroms; + +module_param_call(cdrom, ide_set_dev_param_mask, NULL, &ide_cdroms, 0); +MODULE_PARM_DESC(cdrom, "force device as a CD-ROM"); + +struct chs_geom { + unsigned int cyl; + u8 head; + u8 sect; +}; + +static unsigned int ide_disks; +static struct chs_geom ide_disks_chs[MAX_HWIFS * MAX_DRIVES]; + +static int ide_set_disk_chs(const char *str, struct kernel_param *kp) +{ + int a, b, c = 0, h = 0, s = 0, i, j = 1; + + if (sscanf(str, "%d.%d:%d,%d,%d", &a, &b, &c, &h, &s) != 5 && + sscanf(str, "%d.%d:%d", &a, &b, &j) != 3) + return -EINVAL; + + i = a * MAX_DRIVES + b; + + if (i >= MAX_HWIFS * MAX_DRIVES || j < 0 || j > 1) + return -EINVAL; + + if (c > INT_MAX || h > 255 || s > 255) + return -EINVAL; + + if (j) + ide_disks |= (1 << i); + else + ide_disks &= (1 << i); + + ide_disks_chs[i].cyl = c; + ide_disks_chs[i].head = h; + ide_disks_chs[i].sect = s; + + return 0; +} + +module_param_call(chs, ide_set_disk_chs, NULL, NULL, 0); +MODULE_PARM_DESC(chs, "force device as a disk (using CHS)"); + static void ide_dev_apply_params(ide_drive_t *drive) { int i = drive->hwif->index * MAX_DRIVES + drive->select.b.unit; @@ -1189,6 +1231,25 @@ static void ide_dev_apply_params(ide_drive_t *drive) drive->name); drive->bad_wstat = BAD_R_STAT; } + if (ide_cdroms & (1 << i)) { + printk(KERN_INFO "ide: forcing %s as a CD-ROM\n", drive->name); + drive->present = 1; + drive->media = ide_cdrom; + /* an ATAPI device ignores DRDY */ + drive->ready_stat = 0; + } + if (ide_disks & (1 << i)) { + drive->cyl = drive->bios_cyl = ide_disks_chs[i].cyl; + drive->head = drive->bios_head = ide_disks_chs[i].head; + drive->sect = drive->bios_sect = ide_disks_chs[i].sect; + drive->forced_geom = 1; + printk(KERN_INFO "ide: forcing %s as a disk (%d/%d/%d)\n", + drive->name, + drive->cyl, drive->head, drive->sect); + drive->present = 1; + drive->media = ide_disk; + drive->ready_stat = READY_STAT; + } } static unsigned int ide_ignore_cable; -- cgit v1.2.3 From 9dcba7f2b7697db787741cf6698bf5c95130ffce Mon Sep 17 00:00:00 2001 From: Bartlomiej Zolnierkiewicz Date: Sun, 27 Apr 2008 15:38:30 +0200 Subject: gayle: add "doubler" parameter * Add "doubler" parameter to enable support for IDE doublers. * Obsolete "ide=doubler" kernel parameter. Cc: Geert Uytterhoeven Signed-off-by: Bartlomiej Zolnierkiewicz --- Documentation/ide/ide.txt | 9 +++------ drivers/ide/ide.c | 2 +- drivers/ide/legacy/gayle.c | 2 ++ 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/ide/ide.txt b/Documentation/ide/ide.txt index caf24b21e7f5..0c78f4b1d9d9 100644 --- a/Documentation/ide/ide.txt +++ b/Documentation/ide/ide.txt @@ -181,12 +181,6 @@ driver using the "options=" keyword to insmod, while replacing any ',' with Summary of ide driver parameters for kernel command line -------------------------------------------------------- - "ide=doubler" : probe/support IDE doublers on Amiga - -There may be more options than shown -- use the source, Luke! - -Everything else is rejected with a "BAD OPTION" message. - For legacy IDE VLB host drivers (ali14xx/dtc2278/ht6560b/qd65xx/umc8672) you need to explicitly enable probing by using "probe" kernel parameter, i.e. to enable probing for ALI M14xx chipsets (ali14xx host driver) use: @@ -203,6 +197,9 @@ are detected automatically). You also need to use "probe" kernel parameter for ide-4drives driver (support for IDE generic chipset with four drives on one port). +To enable support for IDE doublers on Amiga use "doubler" kernel parameter +for gayle host driver (i.e. "gayle.doubler" if the driver is built-in). + To force ignoring cable detection (this should be needed only if you're using short 40-wires cable which cannot be automatically detected - if this is not a case please report it as a bug instead) use "ignore_cable" kernel parameter: diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index a4bceeecde70..a017eb242604 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -866,7 +866,7 @@ static int __init ide_setup(char *s) printk(" : Enabled support for IDE doublers\n"); ide_doubler = 1; - return 1; + goto obsolete_option; } #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ diff --git a/drivers/ide/legacy/gayle.c b/drivers/ide/legacy/gayle.c index a0c9601bdaf0..61a713bf24b5 100644 --- a/drivers/ide/legacy/gayle.c +++ b/drivers/ide/legacy/gayle.c @@ -63,6 +63,8 @@ #define GAYLE_HAS_CONTROL_REG (!ide_doubler) #define GAYLE_IDEREG_SIZE (ide_doubler ? 0x1000 : 0x2000) int ide_doubler = 0; /* support IDE doublers? */ +module_param_named(doubler, ide_doubler, bool, 0); +MODULE_PARM_DESC(doubler, "enable support for IDE doublers"); #endif /* CONFIG_BLK_DEV_IDEDOUBLER */ -- cgit v1.2.3 From bbf45ba57eaec56569918a8bab96ab653bd45ec1 Mon Sep 17 00:00:00 2001 From: Hollis Blanchard Date: Wed, 16 Apr 2008 23:28:09 -0500 Subject: KVM: ppc: PowerPC 440 KVM implementation This functionality is definitely experimental, but is capable of running unmodified PowerPC 440 Linux kernels as guests on a PowerPC 440 host. (Only tested with 440EP "Bamboo" guests so far, but with appropriate userspace support other SoC/board combinations should work.) See Documentation/powerpc/kvm_440.txt for technical details. [stephen: build fix] Signed-off-by: Hollis Blanchard Acked-by: Paul Mackerras Signed-off-by: Stephen Rothwell Signed-off-by: Avi Kivity --- Documentation/powerpc/kvm_440.txt | 41 ++ arch/powerpc/Kconfig | 1 + arch/powerpc/Kconfig.debug | 3 + arch/powerpc/Makefile | 1 + arch/powerpc/kernel/asm-offsets.c | 28 ++ arch/powerpc/kvm/44x_tlb.c | 224 +++++++++++ arch/powerpc/kvm/44x_tlb.h | 91 +++++ arch/powerpc/kvm/Kconfig | 42 ++ arch/powerpc/kvm/Makefile | 15 + arch/powerpc/kvm/booke_guest.c | 615 +++++++++++++++++++++++++++++ arch/powerpc/kvm/booke_host.c | 83 ++++ arch/powerpc/kvm/booke_interrupts.S | 436 +++++++++++++++++++++ arch/powerpc/kvm/emulate.c | 760 ++++++++++++++++++++++++++++++++++++ arch/powerpc/kvm/powerpc.c | 436 +++++++++++++++++++++ include/asm-powerpc/kvm.h | 53 ++- include/asm-powerpc/kvm_asm.h | 55 +++ include/asm-powerpc/kvm_host.h | 152 ++++++++ include/asm-powerpc/kvm_para.h | 37 ++ include/asm-powerpc/kvm_ppc.h | 88 +++++ 19 files changed, 3159 insertions(+), 2 deletions(-) create mode 100644 Documentation/powerpc/kvm_440.txt create mode 100644 arch/powerpc/kvm/44x_tlb.c create mode 100644 arch/powerpc/kvm/44x_tlb.h create mode 100644 arch/powerpc/kvm/Kconfig create mode 100644 arch/powerpc/kvm/Makefile create mode 100644 arch/powerpc/kvm/booke_guest.c create mode 100644 arch/powerpc/kvm/booke_host.c create mode 100644 arch/powerpc/kvm/booke_interrupts.S create mode 100644 arch/powerpc/kvm/emulate.c create mode 100644 arch/powerpc/kvm/powerpc.c create mode 100644 include/asm-powerpc/kvm_asm.h create mode 100644 include/asm-powerpc/kvm_host.h create mode 100644 include/asm-powerpc/kvm_para.h create mode 100644 include/asm-powerpc/kvm_ppc.h (limited to 'Documentation') diff --git a/Documentation/powerpc/kvm_440.txt b/Documentation/powerpc/kvm_440.txt new file mode 100644 index 000000000000..c02a003fa03a --- /dev/null +++ b/Documentation/powerpc/kvm_440.txt @@ -0,0 +1,41 @@ +Hollis Blanchard +15 Apr 2008 + +Various notes on the implementation of KVM for PowerPC 440: + +To enforce isolation, host userspace, guest kernel, and guest userspace all +run at user privilege level. Only the host kernel runs in supervisor mode. +Executing privileged instructions in the guest traps into KVM (in the host +kernel), where we decode and emulate them. Through this technique, unmodified +440 Linux kernels can be run (slowly) as guests. Future performance work will +focus on reducing the overhead and frequency of these traps. + +The usual code flow is started from userspace invoking an "run" ioctl, which +causes KVM to switch into guest context. We use IVPR to hijack the host +interrupt vectors while running the guest, which allows us to direct all +interrupts to kvmppc_handle_interrupt(). At this point, we could either +- handle the interrupt completely (e.g. emulate "mtspr SPRG0"), or +- let the host interrupt handler run (e.g. when the decrementer fires), or +- return to host userspace (e.g. when the guest performs device MMIO) + +Address spaces: We take advantage of the fact that Linux doesn't use the AS=1 +address space (in host or guest), which gives us virtual address space to use +for guest mappings. While the guest is running, the host kernel remains mapped +in AS=0, but the guest can only use AS=1 mappings. + +TLB entries: The TLB entries covering the host linear mapping remain +present while running the guest. This reduces the overhead of lightweight +exits, which are handled by KVM running in the host kernel. We keep three +copies of the TLB: + - guest TLB: contents of the TLB as the guest sees it + - shadow TLB: the TLB that is actually in hardware while guest is running + - host TLB: to restore TLB state when context switching guest -> host +When a TLB miss occurs because a mapping was not present in the shadow TLB, +but was present in the guest TLB, KVM handles the fault without invoking the +guest. Large guest pages are backed by multiple 4KB shadow pages through this +mechanism. + +IO: MMIO and DCR accesses are emulated by userspace. We use virtio for network +and block IO, so those drivers must be enabled in the guest. It's possible +that some qemu device emulation (e.g. e1000 or rtl8139) may also work with +little effort. diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 20f45a8b87e3..4e40c122bf26 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -803,3 +803,4 @@ config PPC_CLOCK config PPC_LIB_RHEAP bool +source "arch/powerpc/kvm/Kconfig" diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug index a86d8d853214..807a2dce6263 100644 --- a/arch/powerpc/Kconfig.debug +++ b/arch/powerpc/Kconfig.debug @@ -151,6 +151,9 @@ config BOOTX_TEXT config PPC_EARLY_DEBUG bool "Early debugging (dangerous)" + # PPC_EARLY_DEBUG on 440 leaves AS=1 mappings above the TLB high water + # mark, which doesn't work with current 440 KVM. + depends on !KVM help Say Y to enable some early debugging facilities that may be available for your processor/board combination. Those facilities are hacks diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile index e2ec4a91ccef..9dcdc036cdf7 100644 --- a/arch/powerpc/Makefile +++ b/arch/powerpc/Makefile @@ -145,6 +145,7 @@ core-y += arch/powerpc/kernel/ \ arch/powerpc/platforms/ core-$(CONFIG_MATH_EMULATION) += arch/powerpc/math-emu/ core-$(CONFIG_XMON) += arch/powerpc/xmon/ +core-$(CONFIG_KVM) += arch/powerpc/kvm/ drivers-$(CONFIG_OPROFILE) += arch/powerpc/oprofile/ diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c index adf1d09d726f..62134845af08 100644 --- a/arch/powerpc/kernel/asm-offsets.c +++ b/arch/powerpc/kernel/asm-offsets.c @@ -23,6 +23,9 @@ #include #include #include +#ifdef CONFIG_KVM +#include +#endif #ifdef CONFIG_PPC64 #include #include @@ -324,5 +327,30 @@ int main(void) DEFINE(PGD_TABLE_SIZE, PGD_TABLE_SIZE); +#ifdef CONFIG_KVM + DEFINE(TLBE_BYTES, sizeof(struct tlbe)); + + DEFINE(VCPU_HOST_STACK, offsetof(struct kvm_vcpu, arch.host_stack)); + DEFINE(VCPU_HOST_PID, offsetof(struct kvm_vcpu, arch.host_pid)); + DEFINE(VCPU_HOST_TLB, offsetof(struct kvm_vcpu, arch.host_tlb)); + DEFINE(VCPU_SHADOW_TLB, offsetof(struct kvm_vcpu, arch.shadow_tlb)); + DEFINE(VCPU_GPRS, offsetof(struct kvm_vcpu, arch.gpr)); + DEFINE(VCPU_LR, offsetof(struct kvm_vcpu, arch.lr)); + DEFINE(VCPU_CR, offsetof(struct kvm_vcpu, arch.cr)); + DEFINE(VCPU_XER, offsetof(struct kvm_vcpu, arch.xer)); + DEFINE(VCPU_CTR, offsetof(struct kvm_vcpu, arch.ctr)); + DEFINE(VCPU_PC, offsetof(struct kvm_vcpu, arch.pc)); + DEFINE(VCPU_MSR, offsetof(struct kvm_vcpu, arch.msr)); + DEFINE(VCPU_SPRG4, offsetof(struct kvm_vcpu, arch.sprg4)); + DEFINE(VCPU_SPRG5, offsetof(struct kvm_vcpu, arch.sprg5)); + DEFINE(VCPU_SPRG6, offsetof(struct kvm_vcpu, arch.sprg6)); + DEFINE(VCPU_SPRG7, offsetof(struct kvm_vcpu, arch.sprg7)); + DEFINE(VCPU_PID, offsetof(struct kvm_vcpu, arch.pid)); + + DEFINE(VCPU_LAST_INST, offsetof(struct kvm_vcpu, arch.last_inst)); + DEFINE(VCPU_FAULT_DEAR, offsetof(struct kvm_vcpu, arch.fault_dear)); + DEFINE(VCPU_FAULT_ESR, offsetof(struct kvm_vcpu, arch.fault_esr)); +#endif + return 0; } diff --git a/arch/powerpc/kvm/44x_tlb.c b/arch/powerpc/kvm/44x_tlb.c new file mode 100644 index 000000000000..f5d7a5eab96e --- /dev/null +++ b/arch/powerpc/kvm/44x_tlb.c @@ -0,0 +1,224 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2007 + * + * Authors: Hollis Blanchard + */ + +#include +#include +#include +#include +#include +#include + +#include "44x_tlb.h" + +#define PPC44x_TLB_USER_PERM_MASK (PPC44x_TLB_UX|PPC44x_TLB_UR|PPC44x_TLB_UW) +#define PPC44x_TLB_SUPER_PERM_MASK (PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW) + +static unsigned int kvmppc_tlb_44x_pos; + +static u32 kvmppc_44x_tlb_shadow_attrib(u32 attrib, int usermode) +{ + /* Mask off reserved bits. */ + attrib &= PPC44x_TLB_PERM_MASK|PPC44x_TLB_ATTR_MASK; + + if (!usermode) { + /* Guest is in supervisor mode, so we need to translate guest + * supervisor permissions into user permissions. */ + attrib &= ~PPC44x_TLB_USER_PERM_MASK; + attrib |= (attrib & PPC44x_TLB_SUPER_PERM_MASK) << 3; + } + + /* Make sure host can always access this memory. */ + attrib |= PPC44x_TLB_SX|PPC44x_TLB_SR|PPC44x_TLB_SW; + + return attrib; +} + +/* Search the guest TLB for a matching entry. */ +int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, unsigned int pid, + unsigned int as) +{ + int i; + + /* XXX Replace loop with fancy data structures. */ + for (i = 0; i < PPC44x_TLB_SIZE; i++) { + struct tlbe *tlbe = &vcpu->arch.guest_tlb[i]; + unsigned int tid; + + if (eaddr < get_tlb_eaddr(tlbe)) + continue; + + if (eaddr > get_tlb_end(tlbe)) + continue; + + tid = get_tlb_tid(tlbe); + if (tid && (tid != pid)) + continue; + + if (!get_tlb_v(tlbe)) + continue; + + if (get_tlb_ts(tlbe) != as) + continue; + + return i; + } + + return -1; +} + +struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr) +{ + unsigned int as = !!(vcpu->arch.msr & MSR_IS); + unsigned int index; + + index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); + if (index == -1) + return NULL; + return &vcpu->arch.guest_tlb[index]; +} + +struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr) +{ + unsigned int as = !!(vcpu->arch.msr & MSR_DS); + unsigned int index; + + index = kvmppc_44x_tlb_index(vcpu, eaddr, vcpu->arch.pid, as); + if (index == -1) + return NULL; + return &vcpu->arch.guest_tlb[index]; +} + +static int kvmppc_44x_tlbe_is_writable(struct tlbe *tlbe) +{ + return tlbe->word2 & (PPC44x_TLB_SW|PPC44x_TLB_UW); +} + +/* Must be called with mmap_sem locked for writing. */ +static void kvmppc_44x_shadow_release(struct kvm_vcpu *vcpu, + unsigned int index) +{ + struct tlbe *stlbe = &vcpu->arch.shadow_tlb[index]; + struct page *page = vcpu->arch.shadow_pages[index]; + + kunmap(vcpu->arch.shadow_pages[index]); + + if (get_tlb_v(stlbe)) { + if (kvmppc_44x_tlbe_is_writable(stlbe)) + kvm_release_page_dirty(page); + else + kvm_release_page_clean(page); + } +} + +/* Caller must ensure that the specified guest TLB entry is safe to insert into + * the shadow TLB. */ +void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, u64 asid, + u32 flags) +{ + struct page *new_page; + struct tlbe *stlbe; + hpa_t hpaddr; + unsigned int victim; + + /* Future optimization: don't overwrite the TLB entry containing the + * current PC (or stack?). */ + victim = kvmppc_tlb_44x_pos++; + if (kvmppc_tlb_44x_pos > tlb_44x_hwater) + kvmppc_tlb_44x_pos = 0; + stlbe = &vcpu->arch.shadow_tlb[victim]; + + /* Get reference to new page. */ + down_write(¤t->mm->mmap_sem); + new_page = gfn_to_page(vcpu->kvm, gfn); + if (is_error_page(new_page)) { + printk(KERN_ERR "Couldn't get guest page!\n"); + kvm_release_page_clean(new_page); + return; + } + hpaddr = page_to_phys(new_page); + + /* Drop reference to old page. */ + kvmppc_44x_shadow_release(vcpu, victim); + up_write(¤t->mm->mmap_sem); + + vcpu->arch.shadow_pages[victim] = new_page; + + /* XXX Make sure (va, size) doesn't overlap any other + * entries. 440x6 user manual says the result would be + * "undefined." */ + + /* XXX what about AS? */ + + stlbe->tid = asid & 0xff; + + /* Force TS=1 for all guest mappings. */ + /* For now we hardcode 4KB mappings, but it will be important to + * use host large pages in the future. */ + stlbe->word0 = (gvaddr & PAGE_MASK) | PPC44x_TLB_VALID | PPC44x_TLB_TS + | PPC44x_TLB_4K; + + stlbe->word1 = (hpaddr & 0xfffffc00) | ((hpaddr >> 32) & 0xf); + stlbe->word2 = kvmppc_44x_tlb_shadow_attrib(flags, + vcpu->arch.msr & MSR_PR); +} + +void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid) +{ + unsigned int pid = asid & 0xff; + int i; + + /* XXX Replace loop with fancy data structures. */ + down_write(¤t->mm->mmap_sem); + for (i = 0; i <= tlb_44x_hwater; i++) { + struct tlbe *stlbe = &vcpu->arch.shadow_tlb[i]; + unsigned int tid; + + if (!get_tlb_v(stlbe)) + continue; + + if (eaddr < get_tlb_eaddr(stlbe)) + continue; + + if (eaddr > get_tlb_end(stlbe)) + continue; + + tid = get_tlb_tid(stlbe); + if (tid && (tid != pid)) + continue; + + kvmppc_44x_shadow_release(vcpu, i); + stlbe->word0 = 0; + } + up_write(¤t->mm->mmap_sem); +} + +/* Invalidate all mappings, so that when they fault back in they will get the + * proper permission bits. */ +void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode) +{ + int i; + + /* XXX Replace loop with fancy data structures. */ + down_write(¤t->mm->mmap_sem); + for (i = 0; i <= tlb_44x_hwater; i++) { + kvmppc_44x_shadow_release(vcpu, i); + vcpu->arch.shadow_tlb[i].word0 = 0; + } + up_write(¤t->mm->mmap_sem); +} diff --git a/arch/powerpc/kvm/44x_tlb.h b/arch/powerpc/kvm/44x_tlb.h new file mode 100644 index 000000000000..2ccd46b6f6b7 --- /dev/null +++ b/arch/powerpc/kvm/44x_tlb.h @@ -0,0 +1,91 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2007 + * + * Authors: Hollis Blanchard + */ + +#ifndef __KVM_POWERPC_TLB_H__ +#define __KVM_POWERPC_TLB_H__ + +#include +#include + +extern int kvmppc_44x_tlb_index(struct kvm_vcpu *vcpu, gva_t eaddr, + unsigned int pid, unsigned int as); +extern struct tlbe *kvmppc_44x_dtlb_search(struct kvm_vcpu *vcpu, gva_t eaddr); +extern struct tlbe *kvmppc_44x_itlb_search(struct kvm_vcpu *vcpu, gva_t eaddr); + +/* TLB helper functions */ +static inline unsigned int get_tlb_size(const struct tlbe *tlbe) +{ + return (tlbe->word0 >> 4) & 0xf; +} + +static inline gva_t get_tlb_eaddr(const struct tlbe *tlbe) +{ + return tlbe->word0 & 0xfffffc00; +} + +static inline gva_t get_tlb_bytes(const struct tlbe *tlbe) +{ + unsigned int pgsize = get_tlb_size(tlbe); + return 1 << 10 << (pgsize << 1); +} + +static inline gva_t get_tlb_end(const struct tlbe *tlbe) +{ + return get_tlb_eaddr(tlbe) + get_tlb_bytes(tlbe) - 1; +} + +static inline u64 get_tlb_raddr(const struct tlbe *tlbe) +{ + u64 word1 = tlbe->word1; + return ((word1 & 0xf) << 32) | (word1 & 0xfffffc00); +} + +static inline unsigned int get_tlb_tid(const struct tlbe *tlbe) +{ + return tlbe->tid & 0xff; +} + +static inline unsigned int get_tlb_ts(const struct tlbe *tlbe) +{ + return (tlbe->word0 >> 8) & 0x1; +} + +static inline unsigned int get_tlb_v(const struct tlbe *tlbe) +{ + return (tlbe->word0 >> 9) & 0x1; +} + +static inline unsigned int get_mmucr_stid(const struct kvm_vcpu *vcpu) +{ + return vcpu->arch.mmucr & 0xff; +} + +static inline unsigned int get_mmucr_sts(const struct kvm_vcpu *vcpu) +{ + return (vcpu->arch.mmucr >> 16) & 0x1; +} + +static inline gpa_t tlb_xlate(struct tlbe *tlbe, gva_t eaddr) +{ + unsigned int pgmask = get_tlb_bytes(tlbe) - 1; + + return get_tlb_raddr(tlbe) | (eaddr & pgmask); +} + +#endif /* __KVM_POWERPC_TLB_H__ */ diff --git a/arch/powerpc/kvm/Kconfig b/arch/powerpc/kvm/Kconfig new file mode 100644 index 000000000000..6b076010213b --- /dev/null +++ b/arch/powerpc/kvm/Kconfig @@ -0,0 +1,42 @@ +# +# KVM configuration +# + +menuconfig VIRTUALIZATION + bool "Virtualization" + ---help--- + Say Y here to get to see options for using your Linux host to run + other operating systems inside virtual machines (guests). + This option alone does not add any kernel code. + + If you say N, all options in this submenu will be skipped and + disabled. + +if VIRTUALIZATION + +config KVM + bool "Kernel-based Virtual Machine (KVM) support" + depends on 44x && EXPERIMENTAL + select PREEMPT_NOTIFIERS + select ANON_INODES + # We can only run on Book E hosts so far + select KVM_BOOKE_HOST + ---help--- + Support hosting virtualized guest machines. You will also + need to select one or more of the processor modules below. + + This module provides access to the hardware capabilities through + a character device node named /dev/kvm. + + If unsure, say N. + +config KVM_BOOKE_HOST + bool "KVM host support for Book E PowerPC processors" + depends on KVM && 44x + ---help--- + Provides host support for KVM on Book E PowerPC processors. Currently + this works on 440 processors only. + +source drivers/virtio/Kconfig + +endif # VIRTUALIZATION diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile new file mode 100644 index 000000000000..d0d358d367ec --- /dev/null +++ b/arch/powerpc/kvm/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for Kernel-based Virtual Machine module +# + +EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm + +common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o) + +kvm-objs := $(common-objs) powerpc.o emulate.o booke_guest.o +obj-$(CONFIG_KVM) += kvm.o + +AFLAGS_booke_interrupts.o := -I$(obj) + +kvm-booke-host-objs := booke_host.o booke_interrupts.o 44x_tlb.o +obj-$(CONFIG_KVM_BOOKE_HOST) += kvm-booke-host.o diff --git a/arch/powerpc/kvm/booke_guest.c b/arch/powerpc/kvm/booke_guest.c new file mode 100644 index 000000000000..6d9884a6884a --- /dev/null +++ b/arch/powerpc/kvm/booke_guest.c @@ -0,0 +1,615 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2007 + * + * Authors: Hollis Blanchard + * Christian Ehrhardt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "44x_tlb.h" + +#define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM +#define VCPU_STAT(x) offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU + +struct kvm_stats_debugfs_item debugfs_entries[] = { + { "exits", VCPU_STAT(sum_exits) }, + { "mmio", VCPU_STAT(mmio_exits) }, + { "dcr", VCPU_STAT(dcr_exits) }, + { "sig", VCPU_STAT(signal_exits) }, + { "light", VCPU_STAT(light_exits) }, + { "itlb_r", VCPU_STAT(itlb_real_miss_exits) }, + { "itlb_v", VCPU_STAT(itlb_virt_miss_exits) }, + { "dtlb_r", VCPU_STAT(dtlb_real_miss_exits) }, + { "dtlb_v", VCPU_STAT(dtlb_virt_miss_exits) }, + { "sysc", VCPU_STAT(syscall_exits) }, + { "isi", VCPU_STAT(isi_exits) }, + { "dsi", VCPU_STAT(dsi_exits) }, + { "inst_emu", VCPU_STAT(emulated_inst_exits) }, + { "dec", VCPU_STAT(dec_exits) }, + { "ext_intr", VCPU_STAT(ext_intr_exits) }, + { NULL } +}; + +static const u32 interrupt_msr_mask[16] = { + [BOOKE_INTERRUPT_CRITICAL] = MSR_ME, + [BOOKE_INTERRUPT_MACHINE_CHECK] = 0, + [BOOKE_INTERRUPT_DATA_STORAGE] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_INST_STORAGE] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_EXTERNAL] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_ALIGNMENT] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_PROGRAM] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_FP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_SYSCALL] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_AP_UNAVAIL] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_DECREMENTER] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_FIT] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_WATCHDOG] = MSR_ME, + [BOOKE_INTERRUPT_DTLB_MISS] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_ITLB_MISS] = MSR_CE|MSR_ME|MSR_DE, + [BOOKE_INTERRUPT_DEBUG] = MSR_ME, +}; + +const unsigned char exception_priority[] = { + [BOOKE_INTERRUPT_DATA_STORAGE] = 0, + [BOOKE_INTERRUPT_INST_STORAGE] = 1, + [BOOKE_INTERRUPT_ALIGNMENT] = 2, + [BOOKE_INTERRUPT_PROGRAM] = 3, + [BOOKE_INTERRUPT_FP_UNAVAIL] = 4, + [BOOKE_INTERRUPT_SYSCALL] = 5, + [BOOKE_INTERRUPT_AP_UNAVAIL] = 6, + [BOOKE_INTERRUPT_DTLB_MISS] = 7, + [BOOKE_INTERRUPT_ITLB_MISS] = 8, + [BOOKE_INTERRUPT_MACHINE_CHECK] = 9, + [BOOKE_INTERRUPT_DEBUG] = 10, + [BOOKE_INTERRUPT_CRITICAL] = 11, + [BOOKE_INTERRUPT_WATCHDOG] = 12, + [BOOKE_INTERRUPT_EXTERNAL] = 13, + [BOOKE_INTERRUPT_FIT] = 14, + [BOOKE_INTERRUPT_DECREMENTER] = 15, +}; + +const unsigned char priority_exception[] = { + BOOKE_INTERRUPT_DATA_STORAGE, + BOOKE_INTERRUPT_INST_STORAGE, + BOOKE_INTERRUPT_ALIGNMENT, + BOOKE_INTERRUPT_PROGRAM, + BOOKE_INTERRUPT_FP_UNAVAIL, + BOOKE_INTERRUPT_SYSCALL, + BOOKE_INTERRUPT_AP_UNAVAIL, + BOOKE_INTERRUPT_DTLB_MISS, + BOOKE_INTERRUPT_ITLB_MISS, + BOOKE_INTERRUPT_MACHINE_CHECK, + BOOKE_INTERRUPT_DEBUG, + BOOKE_INTERRUPT_CRITICAL, + BOOKE_INTERRUPT_WATCHDOG, + BOOKE_INTERRUPT_EXTERNAL, + BOOKE_INTERRUPT_FIT, + BOOKE_INTERRUPT_DECREMENTER, +}; + + +void kvmppc_dump_tlbs(struct kvm_vcpu *vcpu) +{ + struct tlbe *tlbe; + int i; + + printk("vcpu %d TLB dump:\n", vcpu->vcpu_id); + printk("| %2s | %3s | %8s | %8s | %8s |\n", + "nr", "tid", "word0", "word1", "word2"); + + for (i = 0; i < PPC44x_TLB_SIZE; i++) { + tlbe = &vcpu->arch.guest_tlb[i]; + if (tlbe->word0 & PPC44x_TLB_VALID) + printk(" G%2d | %02X | %08X | %08X | %08X |\n", + i, tlbe->tid, tlbe->word0, tlbe->word1, + tlbe->word2); + } + + for (i = 0; i < PPC44x_TLB_SIZE; i++) { + tlbe = &vcpu->arch.shadow_tlb[i]; + if (tlbe->word0 & PPC44x_TLB_VALID) + printk(" S%2d | %02X | %08X | %08X | %08X |\n", + i, tlbe->tid, tlbe->word0, tlbe->word1, + tlbe->word2); + } +} + +/* TODO: use vcpu_printf() */ +void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu) +{ + int i; + + printk("pc: %08x msr: %08x\n", vcpu->arch.pc, vcpu->arch.msr); + printk("lr: %08x ctr: %08x\n", vcpu->arch.lr, vcpu->arch.ctr); + printk("srr0: %08x srr1: %08x\n", vcpu->arch.srr0, vcpu->arch.srr1); + + printk("exceptions: %08lx\n", vcpu->arch.pending_exceptions); + + for (i = 0; i < 32; i += 4) { + printk("gpr%02d: %08x %08x %08x %08x\n", i, + vcpu->arch.gpr[i], + vcpu->arch.gpr[i+1], + vcpu->arch.gpr[i+2], + vcpu->arch.gpr[i+3]); + } +} + +/* Check if we are ready to deliver the interrupt */ +static int kvmppc_can_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) +{ + int r; + + switch (interrupt) { + case BOOKE_INTERRUPT_CRITICAL: + r = vcpu->arch.msr & MSR_CE; + break; + case BOOKE_INTERRUPT_MACHINE_CHECK: + r = vcpu->arch.msr & MSR_ME; + break; + case BOOKE_INTERRUPT_EXTERNAL: + r = vcpu->arch.msr & MSR_EE; + break; + case BOOKE_INTERRUPT_DECREMENTER: + r = vcpu->arch.msr & MSR_EE; + break; + case BOOKE_INTERRUPT_FIT: + r = vcpu->arch.msr & MSR_EE; + break; + case BOOKE_INTERRUPT_WATCHDOG: + r = vcpu->arch.msr & MSR_CE; + break; + case BOOKE_INTERRUPT_DEBUG: + r = vcpu->arch.msr & MSR_DE; + break; + default: + r = 1; + } + + return r; +} + +static void kvmppc_deliver_interrupt(struct kvm_vcpu *vcpu, int interrupt) +{ + switch (interrupt) { + case BOOKE_INTERRUPT_DECREMENTER: + vcpu->arch.tsr |= TSR_DIS; + break; + } + + vcpu->arch.srr0 = vcpu->arch.pc; + vcpu->arch.srr1 = vcpu->arch.msr; + vcpu->arch.pc = vcpu->arch.ivpr | vcpu->arch.ivor[interrupt]; + kvmppc_set_msr(vcpu, vcpu->arch.msr & interrupt_msr_mask[interrupt]); +} + +/* Check pending exceptions and deliver one, if possible. */ +void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu) +{ + unsigned long *pending = &vcpu->arch.pending_exceptions; + unsigned int exception; + unsigned int priority; + + priority = find_first_bit(pending, BITS_PER_BYTE * sizeof(*pending)); + while (priority <= BOOKE_MAX_INTERRUPT) { + exception = priority_exception[priority]; + if (kvmppc_can_deliver_interrupt(vcpu, exception)) { + kvmppc_clear_exception(vcpu, exception); + kvmppc_deliver_interrupt(vcpu, exception); + break; + } + + priority = find_next_bit(pending, + BITS_PER_BYTE * sizeof(*pending), + priority + 1); + } +} + +static int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + enum emulation_result er; + int r; + + er = kvmppc_emulate_instruction(run, vcpu); + switch (er) { + case EMULATE_DONE: + /* Future optimization: only reload non-volatiles if they were + * actually modified. */ + r = RESUME_GUEST_NV; + break; + case EMULATE_DO_MMIO: + run->exit_reason = KVM_EXIT_MMIO; + /* We must reload nonvolatiles because "update" load/store + * instructions modify register state. */ + /* Future optimization: only reload non-volatiles if they were + * actually modified. */ + r = RESUME_HOST_NV; + break; + case EMULATE_FAIL: + /* XXX Deliver Program interrupt to guest. */ + printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__, + vcpu->arch.last_inst); + r = RESUME_HOST; + break; + default: + BUG(); + } + + return r; +} + +/** + * kvmppc_handle_exit + * + * Return value is in the form (errcode<<2 | RESUME_FLAG_HOST | RESUME_FLAG_NV) + */ +int kvmppc_handle_exit(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int exit_nr) +{ + enum emulation_result er; + int r = RESUME_HOST; + + local_irq_enable(); + + run->exit_reason = KVM_EXIT_UNKNOWN; + run->ready_for_interrupt_injection = 1; + + switch (exit_nr) { + case BOOKE_INTERRUPT_MACHINE_CHECK: + printk("MACHINE CHECK: %lx\n", mfspr(SPRN_MCSR)); + kvmppc_dump_vcpu(vcpu); + r = RESUME_HOST; + break; + + case BOOKE_INTERRUPT_EXTERNAL: + case BOOKE_INTERRUPT_DECREMENTER: + /* Since we switched IVPR back to the host's value, the host + * handled this interrupt the moment we enabled interrupts. + * Now we just offer it a chance to reschedule the guest. */ + + /* XXX At this point the TLB still holds our shadow TLB, so if + * we do reschedule the host will fault over it. Perhaps we + * should politely restore the host's entries to minimize + * misses before ceding control. */ + if (need_resched()) + cond_resched(); + if (exit_nr == BOOKE_INTERRUPT_DECREMENTER) + vcpu->stat.dec_exits++; + else + vcpu->stat.ext_intr_exits++; + r = RESUME_GUEST; + break; + + case BOOKE_INTERRUPT_PROGRAM: + if (vcpu->arch.msr & MSR_PR) { + /* Program traps generated by user-level software must be handled + * by the guest kernel. */ + vcpu->arch.esr = vcpu->arch.fault_esr; + kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); + r = RESUME_GUEST; + break; + } + + er = kvmppc_emulate_instruction(run, vcpu); + switch (er) { + case EMULATE_DONE: + /* Future optimization: only reload non-volatiles if + * they were actually modified by emulation. */ + vcpu->stat.emulated_inst_exits++; + r = RESUME_GUEST_NV; + break; + case EMULATE_DO_DCR: + run->exit_reason = KVM_EXIT_DCR; + r = RESUME_HOST; + break; + case EMULATE_FAIL: + /* XXX Deliver Program interrupt to guest. */ + printk(KERN_CRIT "%s: emulation at %x failed (%08x)\n", + __func__, vcpu->arch.pc, vcpu->arch.last_inst); + /* For debugging, encode the failing instruction and + * report it to userspace. */ + run->hw.hardware_exit_reason = ~0ULL << 32; + run->hw.hardware_exit_reason |= vcpu->arch.last_inst; + r = RESUME_HOST; + break; + default: + BUG(); + } + break; + + case BOOKE_INTERRUPT_DATA_STORAGE: + vcpu->arch.dear = vcpu->arch.fault_dear; + vcpu->arch.esr = vcpu->arch.fault_esr; + kvmppc_queue_exception(vcpu, exit_nr); + vcpu->stat.dsi_exits++; + r = RESUME_GUEST; + break; + + case BOOKE_INTERRUPT_INST_STORAGE: + vcpu->arch.esr = vcpu->arch.fault_esr; + kvmppc_queue_exception(vcpu, exit_nr); + vcpu->stat.isi_exits++; + r = RESUME_GUEST; + break; + + case BOOKE_INTERRUPT_SYSCALL: + kvmppc_queue_exception(vcpu, exit_nr); + vcpu->stat.syscall_exits++; + r = RESUME_GUEST; + break; + + case BOOKE_INTERRUPT_DTLB_MISS: { + struct tlbe *gtlbe; + unsigned long eaddr = vcpu->arch.fault_dear; + gfn_t gfn; + + /* Check the guest TLB. */ + gtlbe = kvmppc_44x_dtlb_search(vcpu, eaddr); + if (!gtlbe) { + /* The guest didn't have a mapping for it. */ + kvmppc_queue_exception(vcpu, exit_nr); + vcpu->arch.dear = vcpu->arch.fault_dear; + vcpu->arch.esr = vcpu->arch.fault_esr; + vcpu->stat.dtlb_real_miss_exits++; + r = RESUME_GUEST; + break; + } + + vcpu->arch.paddr_accessed = tlb_xlate(gtlbe, eaddr); + gfn = vcpu->arch.paddr_accessed >> PAGE_SHIFT; + + if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { + /* The guest TLB had a mapping, but the shadow TLB + * didn't, and it is RAM. This could be because: + * a) the entry is mapping the host kernel, or + * b) the guest used a large mapping which we're faking + * Either way, we need to satisfy the fault without + * invoking the guest. */ + kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid, + gtlbe->word2); + vcpu->stat.dtlb_virt_miss_exits++; + r = RESUME_GUEST; + } else { + /* Guest has mapped and accessed a page which is not + * actually RAM. */ + r = kvmppc_emulate_mmio(run, vcpu); + } + + break; + } + + case BOOKE_INTERRUPT_ITLB_MISS: { + struct tlbe *gtlbe; + unsigned long eaddr = vcpu->arch.pc; + gfn_t gfn; + + r = RESUME_GUEST; + + /* Check the guest TLB. */ + gtlbe = kvmppc_44x_itlb_search(vcpu, eaddr); + if (!gtlbe) { + /* The guest didn't have a mapping for it. */ + kvmppc_queue_exception(vcpu, exit_nr); + vcpu->stat.itlb_real_miss_exits++; + break; + } + + vcpu->stat.itlb_virt_miss_exits++; + + gfn = tlb_xlate(gtlbe, eaddr) >> PAGE_SHIFT; + + if (kvm_is_visible_gfn(vcpu->kvm, gfn)) { + /* The guest TLB had a mapping, but the shadow TLB + * didn't. This could be because: + * a) the entry is mapping the host kernel, or + * b) the guest used a large mapping which we're faking + * Either way, we need to satisfy the fault without + * invoking the guest. */ + kvmppc_mmu_map(vcpu, eaddr, gfn, gtlbe->tid, + gtlbe->word2); + } else { + /* Guest mapped and leaped at non-RAM! */ + kvmppc_queue_exception(vcpu, + BOOKE_INTERRUPT_MACHINE_CHECK); + } + + break; + } + + default: + printk(KERN_EMERG "exit_nr %d\n", exit_nr); + BUG(); + } + + local_irq_disable(); + + kvmppc_check_and_deliver_interrupts(vcpu); + + /* Do some exit accounting. */ + vcpu->stat.sum_exits++; + if (!(r & RESUME_HOST)) { + /* To avoid clobbering exit_reason, only check for signals if + * we aren't already exiting to userspace for some other + * reason. */ + if (signal_pending(current)) { + run->exit_reason = KVM_EXIT_INTR; + r = (-EINTR << 2) | RESUME_HOST | (r & RESUME_FLAG_NV); + + vcpu->stat.signal_exits++; + } else { + vcpu->stat.light_exits++; + } + } else { + switch (run->exit_reason) { + case KVM_EXIT_MMIO: + vcpu->stat.mmio_exits++; + break; + case KVM_EXIT_DCR: + vcpu->stat.dcr_exits++; + break; + case KVM_EXIT_INTR: + vcpu->stat.signal_exits++; + break; + } + } + + return r; +} + +/* Initial guest state: 16MB mapping 0 -> 0, PC = 0, MSR = 0, R1 = 16MB */ +int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu) +{ + struct tlbe *tlbe = &vcpu->arch.guest_tlb[0]; + + tlbe->tid = 0; + tlbe->word0 = PPC44x_TLB_16M | PPC44x_TLB_VALID; + tlbe->word1 = 0; + tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR; + + tlbe++; + tlbe->tid = 0; + tlbe->word0 = 0xef600000 | PPC44x_TLB_4K | PPC44x_TLB_VALID; + tlbe->word1 = 0xef600000; + tlbe->word2 = PPC44x_TLB_SX | PPC44x_TLB_SW | PPC44x_TLB_SR + | PPC44x_TLB_I | PPC44x_TLB_G; + + vcpu->arch.pc = 0; + vcpu->arch.msr = 0; + vcpu->arch.gpr[1] = (16<<20) - 8; /* -8 for the callee-save LR slot */ + + /* Eye-catching number so we know if the guest takes an interrupt + * before it's programmed its own IVPR. */ + vcpu->arch.ivpr = 0x55550000; + + /* Since the guest can directly access the timebase, it must know the + * real timebase frequency. Accordingly, it must see the state of + * CCR1[TCS]. */ + vcpu->arch.ccr1 = mfspr(SPRN_CCR1); + + return 0; +} + +int kvm_arch_vcpu_ioctl_get_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) +{ + int i; + + regs->pc = vcpu->arch.pc; + regs->cr = vcpu->arch.cr; + regs->ctr = vcpu->arch.ctr; + regs->lr = vcpu->arch.lr; + regs->xer = vcpu->arch.xer; + regs->msr = vcpu->arch.msr; + regs->srr0 = vcpu->arch.srr0; + regs->srr1 = vcpu->arch.srr1; + regs->pid = vcpu->arch.pid; + regs->sprg0 = vcpu->arch.sprg0; + regs->sprg1 = vcpu->arch.sprg1; + regs->sprg2 = vcpu->arch.sprg2; + regs->sprg3 = vcpu->arch.sprg3; + regs->sprg5 = vcpu->arch.sprg4; + regs->sprg6 = vcpu->arch.sprg5; + regs->sprg7 = vcpu->arch.sprg6; + + for (i = 0; i < ARRAY_SIZE(regs->gpr); i++) + regs->gpr[i] = vcpu->arch.gpr[i]; + + return 0; +} + +int kvm_arch_vcpu_ioctl_set_regs(struct kvm_vcpu *vcpu, struct kvm_regs *regs) +{ + int i; + + vcpu->arch.pc = regs->pc; + vcpu->arch.cr = regs->cr; + vcpu->arch.ctr = regs->ctr; + vcpu->arch.lr = regs->lr; + vcpu->arch.xer = regs->xer; + vcpu->arch.msr = regs->msr; + vcpu->arch.srr0 = regs->srr0; + vcpu->arch.srr1 = regs->srr1; + vcpu->arch.sprg0 = regs->sprg0; + vcpu->arch.sprg1 = regs->sprg1; + vcpu->arch.sprg2 = regs->sprg2; + vcpu->arch.sprg3 = regs->sprg3; + vcpu->arch.sprg5 = regs->sprg4; + vcpu->arch.sprg6 = regs->sprg5; + vcpu->arch.sprg7 = regs->sprg6; + + for (i = 0; i < ARRAY_SIZE(vcpu->arch.gpr); i++) + vcpu->arch.gpr[i] = regs->gpr[i]; + + return 0; +} + +int kvm_arch_vcpu_ioctl_get_sregs(struct kvm_vcpu *vcpu, + struct kvm_sregs *sregs) +{ + return -ENOTSUPP; +} + +int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu, + struct kvm_sregs *sregs) +{ + return -ENOTSUPP; +} + +int kvm_arch_vcpu_ioctl_get_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) +{ + return -ENOTSUPP; +} + +int kvm_arch_vcpu_ioctl_set_fpu(struct kvm_vcpu *vcpu, struct kvm_fpu *fpu) +{ + return -ENOTSUPP; +} + +/* 'linear_address' is actually an encoding of AS|PID|EADDR . */ +int kvm_arch_vcpu_ioctl_translate(struct kvm_vcpu *vcpu, + struct kvm_translation *tr) +{ + struct tlbe *gtlbe; + int index; + gva_t eaddr; + u8 pid; + u8 as; + + eaddr = tr->linear_address; + pid = (tr->linear_address >> 32) & 0xff; + as = (tr->linear_address >> 40) & 0x1; + + index = kvmppc_44x_tlb_index(vcpu, eaddr, pid, as); + if (index == -1) { + tr->valid = 0; + return 0; + } + + gtlbe = &vcpu->arch.guest_tlb[index]; + + tr->physical_address = tlb_xlate(gtlbe, eaddr); + /* XXX what does "writeable" and "usermode" even mean? */ + tr->valid = 1; + + return 0; +} diff --git a/arch/powerpc/kvm/booke_host.c b/arch/powerpc/kvm/booke_host.c new file mode 100644 index 000000000000..b480341bc31e --- /dev/null +++ b/arch/powerpc/kvm/booke_host.c @@ -0,0 +1,83 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2008 + * + * Authors: Hollis Blanchard + */ + +#include +#include +#include +#include +#include + +unsigned long kvmppc_booke_handlers; + +static int kvmppc_booke_init(void) +{ + unsigned long ivor[16]; + unsigned long max_ivor = 0; + int i; + + /* We install our own exception handlers by hijacking IVPR. IVPR must + * be 16-bit aligned, so we need a 64KB allocation. */ + kvmppc_booke_handlers = __get_free_pages(GFP_KERNEL | __GFP_ZERO, + VCPU_SIZE_ORDER); + if (!kvmppc_booke_handlers) + return -ENOMEM; + + /* XXX make sure our handlers are smaller than Linux's */ + + /* Copy our interrupt handlers to match host IVORs. That way we don't + * have to swap the IVORs on every guest/host transition. */ + ivor[0] = mfspr(SPRN_IVOR0); + ivor[1] = mfspr(SPRN_IVOR1); + ivor[2] = mfspr(SPRN_IVOR2); + ivor[3] = mfspr(SPRN_IVOR3); + ivor[4] = mfspr(SPRN_IVOR4); + ivor[5] = mfspr(SPRN_IVOR5); + ivor[6] = mfspr(SPRN_IVOR6); + ivor[7] = mfspr(SPRN_IVOR7); + ivor[8] = mfspr(SPRN_IVOR8); + ivor[9] = mfspr(SPRN_IVOR9); + ivor[10] = mfspr(SPRN_IVOR10); + ivor[11] = mfspr(SPRN_IVOR11); + ivor[12] = mfspr(SPRN_IVOR12); + ivor[13] = mfspr(SPRN_IVOR13); + ivor[14] = mfspr(SPRN_IVOR14); + ivor[15] = mfspr(SPRN_IVOR15); + + for (i = 0; i < 16; i++) { + if (ivor[i] > max_ivor) + max_ivor = ivor[i]; + + memcpy((void *)kvmppc_booke_handlers + ivor[i], + kvmppc_handlers_start + i * kvmppc_handler_len, + kvmppc_handler_len); + } + flush_icache_range(kvmppc_booke_handlers, + kvmppc_booke_handlers + max_ivor + kvmppc_handler_len); + + return kvm_init(NULL, sizeof(struct kvm_vcpu), THIS_MODULE); +} + +static void __exit kvmppc_booke_exit(void) +{ + free_pages(kvmppc_booke_handlers, VCPU_SIZE_ORDER); + kvm_exit(); +} + +module_init(kvmppc_booke_init) +module_exit(kvmppc_booke_exit) diff --git a/arch/powerpc/kvm/booke_interrupts.S b/arch/powerpc/kvm/booke_interrupts.S new file mode 100644 index 000000000000..3b653b5309b8 --- /dev/null +++ b/arch/powerpc/kvm/booke_interrupts.S @@ -0,0 +1,436 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2007 + * + * Authors: Hollis Blanchard + */ + +#include +#include +#include +#include +#include +#include + +#define KVMPPC_MSR_MASK (MSR_CE|MSR_EE|MSR_PR|MSR_DE|MSR_ME|MSR_IS|MSR_DS) + +#define VCPU_GPR(n) (VCPU_GPRS + (n * 4)) + +/* The host stack layout: */ +#define HOST_R1 0 /* Implied by stwu. */ +#define HOST_CALLEE_LR 4 +#define HOST_RUN 8 +/* r2 is special: it holds 'current', and it made nonvolatile in the + * kernel with the -ffixed-r2 gcc option. */ +#define HOST_R2 12 +#define HOST_NV_GPRS 16 +#define HOST_NV_GPR(n) (HOST_NV_GPRS + ((n - 14) * 4)) +#define HOST_MIN_STACK_SIZE (HOST_NV_GPR(31) + 4) +#define HOST_STACK_SIZE (((HOST_MIN_STACK_SIZE + 15) / 16) * 16) /* Align. */ +#define HOST_STACK_LR (HOST_STACK_SIZE + 4) /* In caller stack frame. */ + +#define NEED_INST_MASK ((1< + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "44x_tlb.h" + +/* Instruction decoding */ +static inline unsigned int get_op(u32 inst) +{ + return inst >> 26; +} + +static inline unsigned int get_xop(u32 inst) +{ + return (inst >> 1) & 0x3ff; +} + +static inline unsigned int get_sprn(u32 inst) +{ + return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0); +} + +static inline unsigned int get_dcrn(u32 inst) +{ + return ((inst >> 16) & 0x1f) | ((inst >> 6) & 0x3e0); +} + +static inline unsigned int get_rt(u32 inst) +{ + return (inst >> 21) & 0x1f; +} + +static inline unsigned int get_rs(u32 inst) +{ + return (inst >> 21) & 0x1f; +} + +static inline unsigned int get_ra(u32 inst) +{ + return (inst >> 16) & 0x1f; +} + +static inline unsigned int get_rb(u32 inst) +{ + return (inst >> 11) & 0x1f; +} + +static inline unsigned int get_rc(u32 inst) +{ + return inst & 0x1; +} + +static inline unsigned int get_ws(u32 inst) +{ + return (inst >> 11) & 0x1f; +} + +static inline unsigned int get_d(u32 inst) +{ + return inst & 0xffff; +} + +static int tlbe_is_host_safe(const struct kvm_vcpu *vcpu, + const struct tlbe *tlbe) +{ + gpa_t gpa; + + if (!get_tlb_v(tlbe)) + return 0; + + /* Does it match current guest AS? */ + /* XXX what about IS != DS? */ + if (get_tlb_ts(tlbe) != !!(vcpu->arch.msr & MSR_IS)) + return 0; + + gpa = get_tlb_raddr(tlbe); + if (!gfn_to_memslot(vcpu->kvm, gpa >> PAGE_SHIFT)) + /* Mapping is not for RAM. */ + return 0; + + return 1; +} + +static int kvmppc_emul_tlbwe(struct kvm_vcpu *vcpu, u32 inst) +{ + u64 eaddr; + u64 raddr; + u64 asid; + u32 flags; + struct tlbe *tlbe; + unsigned int ra; + unsigned int rs; + unsigned int ws; + unsigned int index; + + ra = get_ra(inst); + rs = get_rs(inst); + ws = get_ws(inst); + + index = vcpu->arch.gpr[ra]; + if (index > PPC44x_TLB_SIZE) { + printk("%s: index %d\n", __func__, index); + kvmppc_dump_vcpu(vcpu); + return EMULATE_FAIL; + } + + tlbe = &vcpu->arch.guest_tlb[index]; + + /* Invalidate shadow mappings for the about-to-be-clobbered TLBE. */ + if (tlbe->word0 & PPC44x_TLB_VALID) { + eaddr = get_tlb_eaddr(tlbe); + asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid; + kvmppc_mmu_invalidate(vcpu, eaddr, asid); + } + + switch (ws) { + case PPC44x_TLB_PAGEID: + tlbe->tid = vcpu->arch.mmucr & 0xff; + tlbe->word0 = vcpu->arch.gpr[rs]; + break; + + case PPC44x_TLB_XLAT: + tlbe->word1 = vcpu->arch.gpr[rs]; + break; + + case PPC44x_TLB_ATTRIB: + tlbe->word2 = vcpu->arch.gpr[rs]; + break; + + default: + return EMULATE_FAIL; + } + + if (tlbe_is_host_safe(vcpu, tlbe)) { + eaddr = get_tlb_eaddr(tlbe); + raddr = get_tlb_raddr(tlbe); + asid = (tlbe->word0 & PPC44x_TLB_TS) | tlbe->tid; + flags = tlbe->word2 & 0xffff; + + /* Create a 4KB mapping on the host. If the guest wanted a + * large page, only the first 4KB is mapped here and the rest + * are mapped on the fly. */ + kvmppc_mmu_map(vcpu, eaddr, raddr >> PAGE_SHIFT, asid, flags); + } + + return EMULATE_DONE; +} + +static void kvmppc_emulate_dec(struct kvm_vcpu *vcpu) +{ + if (vcpu->arch.tcr & TCR_DIE) { + /* The decrementer ticks at the same rate as the timebase, so + * that's how we convert the guest DEC value to the number of + * host ticks. */ + unsigned long nr_jiffies; + + nr_jiffies = vcpu->arch.dec / tb_ticks_per_jiffy; + mod_timer(&vcpu->arch.dec_timer, + get_jiffies_64() + nr_jiffies); + } else { + del_timer(&vcpu->arch.dec_timer); + } +} + +static void kvmppc_emul_rfi(struct kvm_vcpu *vcpu) +{ + vcpu->arch.pc = vcpu->arch.srr0; + kvmppc_set_msr(vcpu, vcpu->arch.srr1); +} + +/* XXX to do: + * lhax + * lhaux + * lswx + * lswi + * stswx + * stswi + * lha + * lhau + * lmw + * stmw + * + * XXX is_bigendian should depend on MMU mapping or MSR[LE] + */ +int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + u32 inst = vcpu->arch.last_inst; + u32 ea; + int ra; + int rb; + int rc; + int rs; + int rt; + int sprn; + int dcrn; + enum emulation_result emulated = EMULATE_DONE; + int advance = 1; + + switch (get_op(inst)) { + case 3: /* trap */ + printk("trap!\n"); + kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_PROGRAM); + advance = 0; + break; + + case 19: + switch (get_xop(inst)) { + case 50: /* rfi */ + kvmppc_emul_rfi(vcpu); + advance = 0; + break; + + default: + emulated = EMULATE_FAIL; + break; + } + break; + + case 31: + switch (get_xop(inst)) { + + case 83: /* mfmsr */ + rt = get_rt(inst); + vcpu->arch.gpr[rt] = vcpu->arch.msr; + break; + + case 87: /* lbzx */ + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); + break; + + case 131: /* wrtee */ + rs = get_rs(inst); + vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) + | (vcpu->arch.gpr[rs] & MSR_EE); + break; + + case 146: /* mtmsr */ + rs = get_rs(inst); + kvmppc_set_msr(vcpu, vcpu->arch.gpr[rs]); + break; + + case 163: /* wrteei */ + vcpu->arch.msr = (vcpu->arch.msr & ~MSR_EE) + | (inst & MSR_EE); + break; + + case 215: /* stbx */ + rs = get_rs(inst); + emulated = kvmppc_handle_store(run, vcpu, + vcpu->arch.gpr[rs], + 1, 1); + break; + + case 247: /* stbux */ + rs = get_rs(inst); + ra = get_ra(inst); + rb = get_rb(inst); + + ea = vcpu->arch.gpr[rb]; + if (ra) + ea += vcpu->arch.gpr[ra]; + + emulated = kvmppc_handle_store(run, vcpu, + vcpu->arch.gpr[rs], + 1, 1); + vcpu->arch.gpr[rs] = ea; + break; + + case 279: /* lhzx */ + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); + break; + + case 311: /* lhzux */ + rt = get_rt(inst); + ra = get_ra(inst); + rb = get_rb(inst); + + ea = vcpu->arch.gpr[rb]; + if (ra) + ea += vcpu->arch.gpr[ra]; + + emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); + vcpu->arch.gpr[ra] = ea; + break; + + case 323: /* mfdcr */ + dcrn = get_dcrn(inst); + rt = get_rt(inst); + + /* The guest may access CPR0 registers to determine the timebase + * frequency, and it must know the real host frequency because it + * can directly access the timebase registers. + * + * It would be possible to emulate those accesses in userspace, + * but userspace can really only figure out the end frequency. + * We could decompose that into the factors that compute it, but + * that's tricky math, and it's easier to just report the real + * CPR0 values. + */ + switch (dcrn) { + case DCRN_CPR0_CONFIG_ADDR: + vcpu->arch.gpr[rt] = vcpu->arch.cpr0_cfgaddr; + break; + case DCRN_CPR0_CONFIG_DATA: + local_irq_disable(); + mtdcr(DCRN_CPR0_CONFIG_ADDR, + vcpu->arch.cpr0_cfgaddr); + vcpu->arch.gpr[rt] = mfdcr(DCRN_CPR0_CONFIG_DATA); + local_irq_enable(); + break; + default: + run->dcr.dcrn = dcrn; + run->dcr.data = 0; + run->dcr.is_write = 0; + vcpu->arch.io_gpr = rt; + vcpu->arch.dcr_needed = 1; + emulated = EMULATE_DO_DCR; + } + + break; + + case 339: /* mfspr */ + sprn = get_sprn(inst); + rt = get_rt(inst); + + switch (sprn) { + case SPRN_SRR0: + vcpu->arch.gpr[rt] = vcpu->arch.srr0; break; + case SPRN_SRR1: + vcpu->arch.gpr[rt] = vcpu->arch.srr1; break; + case SPRN_MMUCR: + vcpu->arch.gpr[rt] = vcpu->arch.mmucr; break; + case SPRN_PID: + vcpu->arch.gpr[rt] = vcpu->arch.pid; break; + case SPRN_IVPR: + vcpu->arch.gpr[rt] = vcpu->arch.ivpr; break; + case SPRN_CCR0: + vcpu->arch.gpr[rt] = vcpu->arch.ccr0; break; + case SPRN_CCR1: + vcpu->arch.gpr[rt] = vcpu->arch.ccr1; break; + case SPRN_PVR: + vcpu->arch.gpr[rt] = vcpu->arch.pvr; break; + case SPRN_DEAR: + vcpu->arch.gpr[rt] = vcpu->arch.dear; break; + case SPRN_ESR: + vcpu->arch.gpr[rt] = vcpu->arch.esr; break; + case SPRN_DBCR0: + vcpu->arch.gpr[rt] = vcpu->arch.dbcr0; break; + case SPRN_DBCR1: + vcpu->arch.gpr[rt] = vcpu->arch.dbcr1; break; + + /* Note: mftb and TBRL/TBWL are user-accessible, so + * the guest can always access the real TB anyways. + * In fact, we probably will never see these traps. */ + case SPRN_TBWL: + vcpu->arch.gpr[rt] = mftbl(); break; + case SPRN_TBWU: + vcpu->arch.gpr[rt] = mftbu(); break; + + case SPRN_SPRG0: + vcpu->arch.gpr[rt] = vcpu->arch.sprg0; break; + case SPRN_SPRG1: + vcpu->arch.gpr[rt] = vcpu->arch.sprg1; break; + case SPRN_SPRG2: + vcpu->arch.gpr[rt] = vcpu->arch.sprg2; break; + case SPRN_SPRG3: + vcpu->arch.gpr[rt] = vcpu->arch.sprg3; break; + /* Note: SPRG4-7 are user-readable, so we don't get + * a trap. */ + + case SPRN_IVOR0: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[0]; break; + case SPRN_IVOR1: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[1]; break; + case SPRN_IVOR2: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[2]; break; + case SPRN_IVOR3: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[3]; break; + case SPRN_IVOR4: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[4]; break; + case SPRN_IVOR5: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[5]; break; + case SPRN_IVOR6: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[6]; break; + case SPRN_IVOR7: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[7]; break; + case SPRN_IVOR8: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[8]; break; + case SPRN_IVOR9: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[9]; break; + case SPRN_IVOR10: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[10]; break; + case SPRN_IVOR11: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[11]; break; + case SPRN_IVOR12: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[12]; break; + case SPRN_IVOR13: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[13]; break; + case SPRN_IVOR14: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[14]; break; + case SPRN_IVOR15: + vcpu->arch.gpr[rt] = vcpu->arch.ivor[15]; break; + + default: + printk("mfspr: unknown spr %x\n", sprn); + vcpu->arch.gpr[rt] = 0; + break; + } + break; + + case 407: /* sthx */ + rs = get_rs(inst); + ra = get_ra(inst); + rb = get_rb(inst); + + emulated = kvmppc_handle_store(run, vcpu, + vcpu->arch.gpr[rs], + 2, 1); + break; + + case 439: /* sthux */ + rs = get_rs(inst); + ra = get_ra(inst); + rb = get_rb(inst); + + ea = vcpu->arch.gpr[rb]; + if (ra) + ea += vcpu->arch.gpr[ra]; + + emulated = kvmppc_handle_store(run, vcpu, + vcpu->arch.gpr[rs], + 2, 1); + vcpu->arch.gpr[ra] = ea; + break; + + case 451: /* mtdcr */ + dcrn = get_dcrn(inst); + rs = get_rs(inst); + + /* emulate some access in kernel */ + switch (dcrn) { + case DCRN_CPR0_CONFIG_ADDR: + vcpu->arch.cpr0_cfgaddr = vcpu->arch.gpr[rs]; + break; + default: + run->dcr.dcrn = dcrn; + run->dcr.data = vcpu->arch.gpr[rs]; + run->dcr.is_write = 1; + vcpu->arch.dcr_needed = 1; + emulated = EMULATE_DO_DCR; + } + + break; + + case 467: /* mtspr */ + sprn = get_sprn(inst); + rs = get_rs(inst); + switch (sprn) { + case SPRN_SRR0: + vcpu->arch.srr0 = vcpu->arch.gpr[rs]; break; + case SPRN_SRR1: + vcpu->arch.srr1 = vcpu->arch.gpr[rs]; break; + case SPRN_MMUCR: + vcpu->arch.mmucr = vcpu->arch.gpr[rs]; break; + case SPRN_PID: + vcpu->arch.pid = vcpu->arch.gpr[rs]; break; + case SPRN_CCR0: + vcpu->arch.ccr0 = vcpu->arch.gpr[rs]; break; + case SPRN_CCR1: + vcpu->arch.ccr1 = vcpu->arch.gpr[rs]; break; + case SPRN_DEAR: + vcpu->arch.dear = vcpu->arch.gpr[rs]; break; + case SPRN_ESR: + vcpu->arch.esr = vcpu->arch.gpr[rs]; break; + case SPRN_DBCR0: + vcpu->arch.dbcr0 = vcpu->arch.gpr[rs]; break; + case SPRN_DBCR1: + vcpu->arch.dbcr1 = vcpu->arch.gpr[rs]; break; + + /* XXX We need to context-switch the timebase for + * watchdog and FIT. */ + case SPRN_TBWL: break; + case SPRN_TBWU: break; + + case SPRN_DEC: + vcpu->arch.dec = vcpu->arch.gpr[rs]; + kvmppc_emulate_dec(vcpu); + break; + + case SPRN_TSR: + vcpu->arch.tsr &= ~vcpu->arch.gpr[rs]; break; + + case SPRN_TCR: + vcpu->arch.tcr = vcpu->arch.gpr[rs]; + kvmppc_emulate_dec(vcpu); + break; + + case SPRN_SPRG0: + vcpu->arch.sprg0 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG1: + vcpu->arch.sprg1 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG2: + vcpu->arch.sprg2 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG3: + vcpu->arch.sprg3 = vcpu->arch.gpr[rs]; break; + + /* Note: SPRG4-7 are user-readable. These values are + * loaded into the real SPRGs when resuming the + * guest. */ + case SPRN_SPRG4: + vcpu->arch.sprg4 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG5: + vcpu->arch.sprg5 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG6: + vcpu->arch.sprg6 = vcpu->arch.gpr[rs]; break; + case SPRN_SPRG7: + vcpu->arch.sprg7 = vcpu->arch.gpr[rs]; break; + + case SPRN_IVPR: + vcpu->arch.ivpr = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR0: + vcpu->arch.ivor[0] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR1: + vcpu->arch.ivor[1] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR2: + vcpu->arch.ivor[2] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR3: + vcpu->arch.ivor[3] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR4: + vcpu->arch.ivor[4] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR5: + vcpu->arch.ivor[5] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR6: + vcpu->arch.ivor[6] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR7: + vcpu->arch.ivor[7] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR8: + vcpu->arch.ivor[8] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR9: + vcpu->arch.ivor[9] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR10: + vcpu->arch.ivor[10] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR11: + vcpu->arch.ivor[11] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR12: + vcpu->arch.ivor[12] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR13: + vcpu->arch.ivor[13] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR14: + vcpu->arch.ivor[14] = vcpu->arch.gpr[rs]; break; + case SPRN_IVOR15: + vcpu->arch.ivor[15] = vcpu->arch.gpr[rs]; break; + + default: + printk("mtspr: unknown spr %x\n", sprn); + emulated = EMULATE_FAIL; + break; + } + break; + + case 470: /* dcbi */ + /* Do nothing. The guest is performing dcbi because + * hardware DMA is not snooped by the dcache, but + * emulated DMA either goes through the dcache as + * normal writes, or the host kernel has handled dcache + * coherence. */ + break; + + case 534: /* lwbrx */ + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 4, 0); + break; + + case 566: /* tlbsync */ + break; + + case 662: /* stwbrx */ + rs = get_rs(inst); + ra = get_ra(inst); + rb = get_rb(inst); + + emulated = kvmppc_handle_store(run, vcpu, + vcpu->arch.gpr[rs], + 4, 0); + break; + + case 978: /* tlbwe */ + emulated = kvmppc_emul_tlbwe(vcpu, inst); + break; + + case 914: { /* tlbsx */ + int index; + unsigned int as = get_mmucr_sts(vcpu); + unsigned int pid = get_mmucr_stid(vcpu); + + rt = get_rt(inst); + ra = get_ra(inst); + rb = get_rb(inst); + rc = get_rc(inst); + + ea = vcpu->arch.gpr[rb]; + if (ra) + ea += vcpu->arch.gpr[ra]; + + index = kvmppc_44x_tlb_index(vcpu, ea, pid, as); + if (rc) { + if (index < 0) + vcpu->arch.cr &= ~0x20000000; + else + vcpu->arch.cr |= 0x20000000; + } + vcpu->arch.gpr[rt] = index; + + } + break; + + case 790: /* lhbrx */ + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 2, 0); + break; + + case 918: /* sthbrx */ + rs = get_rs(inst); + ra = get_ra(inst); + rb = get_rb(inst); + + emulated = kvmppc_handle_store(run, vcpu, + vcpu->arch.gpr[rs], + 2, 0); + break; + + case 966: /* iccci */ + break; + + default: + printk("unknown: op %d xop %d\n", get_op(inst), + get_xop(inst)); + emulated = EMULATE_FAIL; + break; + } + break; + + case 32: /* lwz */ + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); + break; + + case 33: /* lwzu */ + ra = get_ra(inst); + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 4, 1); + vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; + break; + + case 34: /* lbz */ + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); + break; + + case 35: /* lbzu */ + ra = get_ra(inst); + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 1, 1); + vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; + break; + + case 36: /* stw */ + rs = get_rs(inst); + emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], + 4, 1); + break; + + case 37: /* stwu */ + ra = get_ra(inst); + rs = get_rs(inst); + emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], + 4, 1); + vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; + break; + + case 38: /* stb */ + rs = get_rs(inst); + emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], + 1, 1); + break; + + case 39: /* stbu */ + ra = get_ra(inst); + rs = get_rs(inst); + emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], + 1, 1); + vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; + break; + + case 40: /* lhz */ + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); + break; + + case 41: /* lhzu */ + ra = get_ra(inst); + rt = get_rt(inst); + emulated = kvmppc_handle_load(run, vcpu, rt, 2, 1); + vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; + break; + + case 44: /* sth */ + rs = get_rs(inst); + emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], + 2, 1); + break; + + case 45: /* sthu */ + ra = get_ra(inst); + rs = get_rs(inst); + emulated = kvmppc_handle_store(run, vcpu, vcpu->arch.gpr[rs], + 2, 1); + vcpu->arch.gpr[ra] = vcpu->arch.paddr_accessed; + break; + + default: + printk("unknown op %d\n", get_op(inst)); + emulated = EMULATE_FAIL; + break; + } + + if (advance) + vcpu->arch.pc += 4; /* Advance past emulated instruction. */ + + return emulated; +} diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c new file mode 100644 index 000000000000..bad40bd2d3ac --- /dev/null +++ b/arch/powerpc/kvm/powerpc.c @@ -0,0 +1,436 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2007 + * + * Authors: Hollis Blanchard + * Christian Ehrhardt + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +gfn_t unalias_gfn(struct kvm *kvm, gfn_t gfn) +{ + return gfn; +} + +int kvm_cpu_has_interrupt(struct kvm_vcpu *v) +{ + /* XXX implement me */ + return 0; +} + +int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) +{ + return 1; +} + + +int kvmppc_emulate_mmio(struct kvm_run *run, struct kvm_vcpu *vcpu) +{ + enum emulation_result er; + int r; + + er = kvmppc_emulate_instruction(run, vcpu); + switch (er) { + case EMULATE_DONE: + /* Future optimization: only reload non-volatiles if they were + * actually modified. */ + r = RESUME_GUEST_NV; + break; + case EMULATE_DO_MMIO: + run->exit_reason = KVM_EXIT_MMIO; + /* We must reload nonvolatiles because "update" load/store + * instructions modify register state. */ + /* Future optimization: only reload non-volatiles if they were + * actually modified. */ + r = RESUME_HOST_NV; + break; + case EMULATE_FAIL: + /* XXX Deliver Program interrupt to guest. */ + printk(KERN_EMERG "%s: emulation failed (%08x)\n", __func__, + vcpu->arch.last_inst); + r = RESUME_HOST; + break; + default: + BUG(); + } + + return r; +} + +void kvm_arch_hardware_enable(void *garbage) +{ +} + +void kvm_arch_hardware_disable(void *garbage) +{ +} + +int kvm_arch_hardware_setup(void) +{ + return 0; +} + +void kvm_arch_hardware_unsetup(void) +{ +} + +void kvm_arch_check_processor_compat(void *rtn) +{ + int r; + + if (strcmp(cur_cpu_spec->platform, "ppc440") == 0) + r = 0; + else + r = -ENOTSUPP; + + *(int *)rtn = r; +} + +struct kvm *kvm_arch_create_vm(void) +{ + struct kvm *kvm; + + kvm = kzalloc(sizeof(struct kvm), GFP_KERNEL); + if (!kvm) + return ERR_PTR(-ENOMEM); + + return kvm; +} + +static void kvmppc_free_vcpus(struct kvm *kvm) +{ + unsigned int i; + + for (i = 0; i < KVM_MAX_VCPUS; ++i) { + if (kvm->vcpus[i]) { + kvm_arch_vcpu_free(kvm->vcpus[i]); + kvm->vcpus[i] = NULL; + } + } +} + +void kvm_arch_destroy_vm(struct kvm *kvm) +{ + kvmppc_free_vcpus(kvm); + kvm_free_physmem(kvm); + kfree(kvm); +} + +int kvm_dev_ioctl_check_extension(long ext) +{ + int r; + + switch (ext) { + case KVM_CAP_USER_MEMORY: + r = 1; + break; + default: + r = 0; + break; + } + return r; + +} + +long kvm_arch_dev_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + return -EINVAL; +} + +int kvm_arch_set_memory_region(struct kvm *kvm, + struct kvm_userspace_memory_region *mem, + struct kvm_memory_slot old, + int user_alloc) +{ + return 0; +} + +struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id) +{ + struct kvm_vcpu *vcpu; + int err; + + vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL); + if (!vcpu) { + err = -ENOMEM; + goto out; + } + + err = kvm_vcpu_init(vcpu, kvm, id); + if (err) + goto free_vcpu; + + return vcpu; + +free_vcpu: + kmem_cache_free(kvm_vcpu_cache, vcpu); +out: + return ERR_PTR(err); +} + +void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu) +{ + kvm_vcpu_uninit(vcpu); + kmem_cache_free(kvm_vcpu_cache, vcpu); +} + +void kvm_arch_vcpu_destroy(struct kvm_vcpu *vcpu) +{ + kvm_arch_vcpu_free(vcpu); +} + +int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu) +{ + unsigned int priority = exception_priority[BOOKE_INTERRUPT_DECREMENTER]; + + return test_bit(priority, &vcpu->arch.pending_exceptions); +} + +static void kvmppc_decrementer_func(unsigned long data) +{ + struct kvm_vcpu *vcpu = (struct kvm_vcpu *)data; + + kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_DECREMENTER); +} + +int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu) +{ + setup_timer(&vcpu->arch.dec_timer, kvmppc_decrementer_func, + (unsigned long)vcpu); + + return 0; +} + +void kvm_arch_vcpu_uninit(struct kvm_vcpu *vcpu) +{ +} + +void kvm_arch_vcpu_load(struct kvm_vcpu *vcpu, int cpu) +{ +} + +void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) +{ +} + +void decache_vcpus_on_cpu(int cpu) +{ +} + +int kvm_arch_vcpu_ioctl_debug_guest(struct kvm_vcpu *vcpu, + struct kvm_debug_guest *dbg) +{ + return -ENOTSUPP; +} + +static void kvmppc_complete_dcr_load(struct kvm_vcpu *vcpu, + struct kvm_run *run) +{ + u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr]; + *gpr = run->dcr.data; +} + +static void kvmppc_complete_mmio_load(struct kvm_vcpu *vcpu, + struct kvm_run *run) +{ + u32 *gpr = &vcpu->arch.gpr[vcpu->arch.io_gpr]; + + if (run->mmio.len > sizeof(*gpr)) { + printk(KERN_ERR "bad MMIO length: %d\n", run->mmio.len); + return; + } + + if (vcpu->arch.mmio_is_bigendian) { + switch (run->mmio.len) { + case 4: *gpr = *(u32 *)run->mmio.data; break; + case 2: *gpr = *(u16 *)run->mmio.data; break; + case 1: *gpr = *(u8 *)run->mmio.data; break; + } + } else { + /* Convert BE data from userland back to LE. */ + switch (run->mmio.len) { + case 4: *gpr = ld_le32((u32 *)run->mmio.data); break; + case 2: *gpr = ld_le16((u16 *)run->mmio.data); break; + case 1: *gpr = *(u8 *)run->mmio.data; break; + } + } +} + +int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int rt, unsigned int bytes, int is_bigendian) +{ + if (bytes > sizeof(run->mmio.data)) { + printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, + run->mmio.len); + } + + run->mmio.phys_addr = vcpu->arch.paddr_accessed; + run->mmio.len = bytes; + run->mmio.is_write = 0; + + vcpu->arch.io_gpr = rt; + vcpu->arch.mmio_is_bigendian = is_bigendian; + vcpu->mmio_needed = 1; + vcpu->mmio_is_write = 0; + + return EMULATE_DO_MMIO; +} + +int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, + u32 val, unsigned int bytes, int is_bigendian) +{ + void *data = run->mmio.data; + + if (bytes > sizeof(run->mmio.data)) { + printk(KERN_ERR "%s: bad MMIO length: %d\n", __func__, + run->mmio.len); + } + + run->mmio.phys_addr = vcpu->arch.paddr_accessed; + run->mmio.len = bytes; + run->mmio.is_write = 1; + vcpu->mmio_needed = 1; + vcpu->mmio_is_write = 1; + + /* Store the value at the lowest bytes in 'data'. */ + if (is_bigendian) { + switch (bytes) { + case 4: *(u32 *)data = val; break; + case 2: *(u16 *)data = val; break; + case 1: *(u8 *)data = val; break; + } + } else { + /* Store LE value into 'data'. */ + switch (bytes) { + case 4: st_le32(data, val); break; + case 2: st_le16(data, val); break; + case 1: *(u8 *)data = val; break; + } + } + + return EMULATE_DO_MMIO; +} + +int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) +{ + int r; + sigset_t sigsaved; + + if (vcpu->sigset_active) + sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved); + + if (vcpu->mmio_needed) { + if (!vcpu->mmio_is_write) + kvmppc_complete_mmio_load(vcpu, run); + vcpu->mmio_needed = 0; + } else if (vcpu->arch.dcr_needed) { + if (!vcpu->arch.dcr_is_write) + kvmppc_complete_dcr_load(vcpu, run); + vcpu->arch.dcr_needed = 0; + } + + kvmppc_check_and_deliver_interrupts(vcpu); + + local_irq_disable(); + kvm_guest_enter(); + r = __kvmppc_vcpu_run(run, vcpu); + kvm_guest_exit(); + local_irq_enable(); + + if (vcpu->sigset_active) + sigprocmask(SIG_SETMASK, &sigsaved, NULL); + + return r; +} + +int kvm_vcpu_ioctl_interrupt(struct kvm_vcpu *vcpu, struct kvm_interrupt *irq) +{ + kvmppc_queue_exception(vcpu, BOOKE_INTERRUPT_EXTERNAL); + return 0; +} + +int kvm_arch_vcpu_ioctl_get_mpstate(struct kvm_vcpu *vcpu, + struct kvm_mp_state *mp_state) +{ + return -EINVAL; +} + +int kvm_arch_vcpu_ioctl_set_mpstate(struct kvm_vcpu *vcpu, + struct kvm_mp_state *mp_state) +{ + return -EINVAL; +} + +long kvm_arch_vcpu_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + struct kvm_vcpu *vcpu = filp->private_data; + void __user *argp = (void __user *)arg; + long r; + + switch (ioctl) { + case KVM_INTERRUPT: { + struct kvm_interrupt irq; + r = -EFAULT; + if (copy_from_user(&irq, argp, sizeof(irq))) + goto out; + r = kvm_vcpu_ioctl_interrupt(vcpu, &irq); + break; + } + default: + r = -EINVAL; + } + +out: + return r; +} + +int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm, struct kvm_dirty_log *log) +{ + return -ENOTSUPP; +} + +long kvm_arch_vm_ioctl(struct file *filp, + unsigned int ioctl, unsigned long arg) +{ + long r; + + switch (ioctl) { + default: + r = -EINVAL; + } + + return r; +} + +int kvm_arch_init(void *opaque) +{ + return 0; +} + +void kvm_arch_exit(void) +{ +} diff --git a/include/asm-powerpc/kvm.h b/include/asm-powerpc/kvm.h index d1b530fbf8dd..f993e4198d5c 100644 --- a/include/asm-powerpc/kvm.h +++ b/include/asm-powerpc/kvm.h @@ -1,6 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2007 + * + * Authors: Hollis Blanchard + */ + #ifndef __LINUX_KVM_POWERPC_H #define __LINUX_KVM_POWERPC_H -/* powerpc does not support KVM */ +#include + +struct kvm_regs { + __u64 pc; + __u64 cr; + __u64 ctr; + __u64 lr; + __u64 xer; + __u64 msr; + __u64 srr0; + __u64 srr1; + __u64 pid; + + __u64 sprg0; + __u64 sprg1; + __u64 sprg2; + __u64 sprg3; + __u64 sprg4; + __u64 sprg5; + __u64 sprg6; + __u64 sprg7; + + __u64 gpr[32]; +}; + +struct kvm_sregs { +}; + +struct kvm_fpu { + __u64 fpr[32]; +}; -#endif +#endif /* __LINUX_KVM_POWERPC_H */ diff --git a/include/asm-powerpc/kvm_asm.h b/include/asm-powerpc/kvm_asm.h new file mode 100644 index 000000000000..2197764796d9 --- /dev/null +++ b/include/asm-powerpc/kvm_asm.h @@ -0,0 +1,55 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2008 + * + * Authors: Hollis Blanchard + */ + +#ifndef __POWERPC_KVM_ASM_H__ +#define __POWERPC_KVM_ASM_H__ + +/* IVPR must be 64KiB-aligned. */ +#define VCPU_SIZE_ORDER 4 +#define VCPU_SIZE_LOG (VCPU_SIZE_ORDER + 12) +#define VCPU_TLB_PGSZ PPC44x_TLB_64K +#define VCPU_SIZE_BYTES (1< + */ + +#ifndef __POWERPC_KVM_HOST_H__ +#define __POWERPC_KVM_HOST_H__ + +#include +#include +#include +#include +#include + +#define KVM_MAX_VCPUS 1 +#define KVM_MEMORY_SLOTS 32 +/* memory slots that does not exposed to userspace */ +#define KVM_PRIVATE_MEM_SLOTS 4 + +/* We don't currently support large pages. */ +#define KVM_PAGES_PER_HPAGE (1<<31) + +struct kvm; +struct kvm_run; +struct kvm_vcpu; + +struct kvm_vm_stat { + u32 remote_tlb_flush; +}; + +struct kvm_vcpu_stat { + u32 sum_exits; + u32 mmio_exits; + u32 dcr_exits; + u32 signal_exits; + u32 light_exits; + /* Account for special types of light exits: */ + u32 itlb_real_miss_exits; + u32 itlb_virt_miss_exits; + u32 dtlb_real_miss_exits; + u32 dtlb_virt_miss_exits; + u32 syscall_exits; + u32 isi_exits; + u32 dsi_exits; + u32 emulated_inst_exits; + u32 dec_exits; + u32 ext_intr_exits; +}; + +struct tlbe { + u32 tid; /* Only the low 8 bits are used. */ + u32 word0; + u32 word1; + u32 word2; +}; + +struct kvm_arch { +}; + +struct kvm_vcpu_arch { + /* Unmodified copy of the guest's TLB. */ + struct tlbe guest_tlb[PPC44x_TLB_SIZE]; + /* TLB that's actually used when the guest is running. */ + struct tlbe shadow_tlb[PPC44x_TLB_SIZE]; + /* Pages which are referenced in the shadow TLB. */ + struct page *shadow_pages[PPC44x_TLB_SIZE]; + /* Copy of the host's TLB. */ + struct tlbe host_tlb[PPC44x_TLB_SIZE]; + + u32 host_stack; + u32 host_pid; + + u64 fpr[32]; + u32 gpr[32]; + + u32 pc; + u32 cr; + u32 ctr; + u32 lr; + u32 xer; + + u32 msr; + u32 mmucr; + u32 sprg0; + u32 sprg1; + u32 sprg2; + u32 sprg3; + u32 sprg4; + u32 sprg5; + u32 sprg6; + u32 sprg7; + u32 srr0; + u32 srr1; + u32 csrr0; + u32 csrr1; + u32 dsrr0; + u32 dsrr1; + u32 dear; + u32 esr; + u32 dec; + u32 decar; + u32 tbl; + u32 tbu; + u32 tcr; + u32 tsr; + u32 ivor[16]; + u32 ivpr; + u32 pir; + u32 pid; + u32 pvr; + u32 ccr0; + u32 ccr1; + u32 dbcr0; + u32 dbcr1; + + u32 last_inst; + u32 fault_dear; + u32 fault_esr; + gpa_t paddr_accessed; + + u8 io_gpr; /* GPR used as IO source/target */ + u8 mmio_is_bigendian; + u8 dcr_needed; + u8 dcr_is_write; + + u32 cpr0_cfgaddr; /* holds the last set cpr0_cfgaddr */ + + struct timer_list dec_timer; + unsigned long pending_exceptions; +}; + +struct kvm_guest_debug { + int enabled; + unsigned long bp[4]; + int singlestep; +}; + +#endif /* __POWERPC_KVM_HOST_H__ */ diff --git a/include/asm-powerpc/kvm_para.h b/include/asm-powerpc/kvm_para.h new file mode 100644 index 000000000000..2d48f6a63d0b --- /dev/null +++ b/include/asm-powerpc/kvm_para.h @@ -0,0 +1,37 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2008 + * + * Authors: Hollis Blanchard + */ + +#ifndef __POWERPC_KVM_PARA_H__ +#define __POWERPC_KVM_PARA_H__ + +#ifdef __KERNEL__ + +static inline int kvm_para_available(void) +{ + return 0; +} + +static inline unsigned int kvm_arch_para_features(void) +{ + return 0; +} + +#endif /* __KERNEL__ */ + +#endif /* __POWERPC_KVM_PARA_H__ */ diff --git a/include/asm-powerpc/kvm_ppc.h b/include/asm-powerpc/kvm_ppc.h new file mode 100644 index 000000000000..7ac820308a7e --- /dev/null +++ b/include/asm-powerpc/kvm_ppc.h @@ -0,0 +1,88 @@ +/* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License, version 2, as + * published by the Free Software Foundation. + * + * 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, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Copyright IBM Corp. 2008 + * + * Authors: Hollis Blanchard + */ + +#ifndef __POWERPC_KVM_PPC_H__ +#define __POWERPC_KVM_PPC_H__ + +/* This file exists just so we can dereference kvm_vcpu, avoiding nested header + * dependencies. */ + +#include +#include +#include +#include +#include + +struct kvm_tlb { + struct tlbe guest_tlb[PPC44x_TLB_SIZE]; + struct tlbe shadow_tlb[PPC44x_TLB_SIZE]; +}; + +enum emulation_result { + EMULATE_DONE, /* no further processing */ + EMULATE_DO_MMIO, /* kvm_run filled with MMIO request */ + EMULATE_DO_DCR, /* kvm_run filled with DCR request */ + EMULATE_FAIL, /* can't emulate this instruction */ +}; + +extern const unsigned char exception_priority[]; +extern const unsigned char priority_exception[]; + +extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu); +extern char kvmppc_handlers_start[]; +extern unsigned long kvmppc_handler_len; + +extern void kvmppc_dump_vcpu(struct kvm_vcpu *vcpu); +extern int kvmppc_handle_load(struct kvm_run *run, struct kvm_vcpu *vcpu, + unsigned int rt, unsigned int bytes, + int is_bigendian); +extern int kvmppc_handle_store(struct kvm_run *run, struct kvm_vcpu *vcpu, + u32 val, unsigned int bytes, int is_bigendian); + +extern int kvmppc_emulate_instruction(struct kvm_run *run, + struct kvm_vcpu *vcpu); + +extern void kvmppc_mmu_map(struct kvm_vcpu *vcpu, u64 gvaddr, gfn_t gfn, + u64 asid, u32 flags); +extern void kvmppc_mmu_invalidate(struct kvm_vcpu *vcpu, u64 eaddr, u64 asid); +extern void kvmppc_mmu_priv_switch(struct kvm_vcpu *vcpu, int usermode); + +extern void kvmppc_check_and_deliver_interrupts(struct kvm_vcpu *vcpu); + +static inline void kvmppc_queue_exception(struct kvm_vcpu *vcpu, int exception) +{ + unsigned int priority = exception_priority[exception]; + set_bit(priority, &vcpu->arch.pending_exceptions); +} + +static inline void kvmppc_clear_exception(struct kvm_vcpu *vcpu, int exception) +{ + unsigned int priority = exception_priority[exception]; + clear_bit(priority, &vcpu->arch.pending_exceptions); +} + +static inline void kvmppc_set_msr(struct kvm_vcpu *vcpu, u32 new_msr) +{ + if ((new_msr & MSR_PR) != (vcpu->arch.msr & MSR_PR)) + kvmppc_mmu_priv_switch(vcpu, new_msr & MSR_PR); + + vcpu->arch.msr = new_msr; +} + +#endif /* __POWERPC_KVM_PPC_H__ */ -- cgit v1.2.3 From 205ab99dd103e3dd5b0964dad8a16dfe2db69b2e Mon Sep 17 00:00:00 2001 From: Christoph Lameter Date: Mon, 14 Apr 2008 19:11:40 +0300 Subject: slub: Update statistics handling for variable order slabs Change the statistics to consider that slabs of the same slabcache can have different number of objects in them since they may be of different order. Provide a new sysfs field total_objects which shows the total objects that the allocated slabs of a slabcache could hold. Add a max field that holds the largest slab order that was ever used for a slab cache. Signed-off-by: Christoph Lameter Signed-off-by: Pekka Enberg --- Documentation/vm/slabinfo.c | 27 ++++---- include/linux/slub_def.h | 2 + mm/slub.c | 150 ++++++++++++++++++++++++++++---------------- 3 files changed, 110 insertions(+), 69 deletions(-) (limited to 'Documentation') diff --git a/Documentation/vm/slabinfo.c b/Documentation/vm/slabinfo.c index 22d7e3e4d60c..d3ce295bffac 100644 --- a/Documentation/vm/slabinfo.c +++ b/Documentation/vm/slabinfo.c @@ -31,7 +31,7 @@ struct slabinfo { int hwcache_align, object_size, objs_per_slab; int sanity_checks, slab_size, store_user, trace; int order, poison, reclaim_account, red_zone; - unsigned long partial, objects, slabs; + unsigned long partial, objects, slabs, objects_partial, objects_total; unsigned long alloc_fastpath, alloc_slowpath; unsigned long free_fastpath, free_slowpath; unsigned long free_frozen, free_add_partial, free_remove_partial; @@ -540,7 +540,8 @@ void slabcache(struct slabinfo *s) return; store_size(size_str, slab_size(s)); - snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs, s->partial, s->cpu_slabs); + snprintf(dist_str, 40, "%lu/%lu/%d", s->slabs - s->cpu_slabs, + s->partial, s->cpu_slabs); if (!line++) first_line(); @@ -776,7 +777,6 @@ void totals(void) unsigned long used; unsigned long long wasted; unsigned long long objwaste; - long long objects_in_partial_slabs; unsigned long percentage_partial_slabs; unsigned long percentage_partial_objs; @@ -790,18 +790,11 @@ void totals(void) wasted = size - used; objwaste = s->slab_size - s->object_size; - objects_in_partial_slabs = s->objects - - (s->slabs - s->partial - s ->cpu_slabs) * - s->objs_per_slab; - - if (objects_in_partial_slabs < 0) - objects_in_partial_slabs = 0; - percentage_partial_slabs = s->partial * 100 / s->slabs; if (percentage_partial_slabs > 100) percentage_partial_slabs = 100; - percentage_partial_objs = objects_in_partial_slabs * 100 + percentage_partial_objs = s->objects_partial * 100 / s->objects; if (percentage_partial_objs > 100) @@ -823,8 +816,8 @@ void totals(void) min_objects = s->objects; if (used < min_used) min_used = used; - if (objects_in_partial_slabs < min_partobj) - min_partobj = objects_in_partial_slabs; + if (s->objects_partial < min_partobj) + min_partobj = s->objects_partial; if (percentage_partial_slabs < min_ppart) min_ppart = percentage_partial_slabs; if (percentage_partial_objs < min_ppartobj) @@ -848,8 +841,8 @@ void totals(void) max_objects = s->objects; if (used > max_used) max_used = used; - if (objects_in_partial_slabs > max_partobj) - max_partobj = objects_in_partial_slabs; + if (s->objects_partial > max_partobj) + max_partobj = s->objects_partial; if (percentage_partial_slabs > max_ppart) max_ppart = percentage_partial_slabs; if (percentage_partial_objs > max_ppartobj) @@ -864,7 +857,7 @@ void totals(void) total_objects += s->objects; total_used += used; - total_partobj += objects_in_partial_slabs; + total_partobj += s->objects_partial; total_ppart += percentage_partial_slabs; total_ppartobj += percentage_partial_objs; @@ -1160,6 +1153,8 @@ void read_slab_dir(void) slab->hwcache_align = get_obj("hwcache_align"); slab->object_size = get_obj("object_size"); slab->objects = get_obj("objects"); + slab->objects_partial = get_obj("objects_partial"); + slab->objects_total = get_obj("objects_total"); slab->objs_per_slab = get_obj("objs_per_slab"); slab->order = get_obj("order"); slab->partial = get_obj("partial"); diff --git a/include/linux/slub_def.h b/include/linux/slub_def.h index 4131e5fbd18b..4236b5dee812 100644 --- a/include/linux/slub_def.h +++ b/include/linux/slub_def.h @@ -48,6 +48,7 @@ struct kmem_cache_node { struct list_head partial; #ifdef CONFIG_SLUB_DEBUG atomic_long_t nr_slabs; + atomic_long_t total_objects; struct list_head full; #endif }; @@ -79,6 +80,7 @@ struct kmem_cache { struct kmem_cache_node local_node; /* Allocation and freeing of slabs */ + struct kmem_cache_order_objects max; gfp_t allocflags; /* gfp flags to use on each alloc */ int refcount; /* Refcount for slab cache destroy */ void (*ctor)(struct kmem_cache *, void *); diff --git a/mm/slub.c b/mm/slub.c index 0a220df5ed7c..c8514e93ffdf 100644 --- a/mm/slub.c +++ b/mm/slub.c @@ -886,7 +886,7 @@ static inline unsigned long slabs_node(struct kmem_cache *s, int node) return atomic_long_read(&n->nr_slabs); } -static inline void inc_slabs_node(struct kmem_cache *s, int node) +static inline void inc_slabs_node(struct kmem_cache *s, int node, int objects) { struct kmem_cache_node *n = get_node(s, node); @@ -896,14 +896,17 @@ static inline void inc_slabs_node(struct kmem_cache *s, int node) * dilemma by deferring the increment of the count during * bootstrap (see early_kmem_cache_node_alloc). */ - if (!NUMA_BUILD || n) + if (!NUMA_BUILD || n) { atomic_long_inc(&n->nr_slabs); + atomic_long_add(objects, &n->total_objects); + } } -static inline void dec_slabs_node(struct kmem_cache *s, int node) +static inline void dec_slabs_node(struct kmem_cache *s, int node, int objects) { struct kmem_cache_node *n = get_node(s, node); atomic_long_dec(&n->nr_slabs); + atomic_long_sub(objects, &n->total_objects); } /* Object debug checks for alloc/free paths */ @@ -1101,9 +1104,12 @@ static inline unsigned long kmem_cache_flags(unsigned long objsize, static inline unsigned long slabs_node(struct kmem_cache *s, int node) { return 0; } -static inline void inc_slabs_node(struct kmem_cache *s, int node) {} -static inline void dec_slabs_node(struct kmem_cache *s, int node) {} +static inline void inc_slabs_node(struct kmem_cache *s, int node, + int objects) {} +static inline void dec_slabs_node(struct kmem_cache *s, int node, + int objects) {} #endif + /* * Slab allocation and freeing */ @@ -1155,7 +1161,7 @@ static struct page *new_slab(struct kmem_cache *s, gfp_t flags, int node) if (!page) goto out; - inc_slabs_node(s, page_to_nid(page)); + inc_slabs_node(s, page_to_nid(page), page->objects); page->slab = s; page->flags |= 1 << PG_slab; if (s->flags & (SLAB_DEBUG_FREE | SLAB_RED_ZONE | SLAB_POISON | @@ -1230,7 +1236,7 @@ static void free_slab(struct kmem_cache *s, struct page *page) static void discard_slab(struct kmem_cache *s, struct page *page) { - dec_slabs_node(s, page_to_nid(page)); + dec_slabs_node(s, page_to_nid(page), page->objects); free_slab(s, page); } @@ -2144,7 +2150,7 @@ static struct kmem_cache_node *early_kmem_cache_node_alloc(gfp_t gfpflags, init_tracking(kmalloc_caches, n); #endif init_kmem_cache_node(n); - inc_slabs_node(kmalloc_caches, node); + inc_slabs_node(kmalloc_caches, node, page->objects); /* * lockdep requires consistent irq usage for each lock @@ -2341,6 +2347,8 @@ static int calculate_sizes(struct kmem_cache *s) * Determine the number of objects per slab */ s->oo = oo_make(order, size); + if (oo_objects(s->oo) > oo_objects(s->max)) + s->max = s->oo; return !!oo_objects(s->oo); @@ -2813,7 +2821,7 @@ int kmem_cache_shrink(struct kmem_cache *s) struct kmem_cache_node *n; struct page *page; struct page *t; - int objects = oo_objects(s->oo); + int objects = oo_objects(s->max); struct list_head *slabs_by_inuse = kmalloc(sizeof(struct list_head) * objects, GFP_KERNEL); unsigned long flags; @@ -3276,7 +3284,8 @@ void *__kmalloc_node_track_caller(size_t size, gfp_t gfpflags, } #if (defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG)) || defined(CONFIG_SLABINFO) -static unsigned long count_partial(struct kmem_cache_node *n) +static unsigned long count_partial(struct kmem_cache_node *n, + int (*get_count)(struct page *)) { unsigned long flags; unsigned long x = 0; @@ -3284,10 +3293,25 @@ static unsigned long count_partial(struct kmem_cache_node *n) spin_lock_irqsave(&n->list_lock, flags); list_for_each_entry(page, &n->partial, lru) - x += page->inuse; + x += get_count(page); spin_unlock_irqrestore(&n->list_lock, flags); return x; } + +static int count_inuse(struct page *page) +{ + return page->inuse; +} + +static int count_total(struct page *page) +{ + return page->objects; +} + +static int count_free(struct page *page) +{ + return page->objects - page->inuse; +} #endif #if defined(CONFIG_SYSFS) && defined(CONFIG_SLUB_DEBUG) @@ -3376,7 +3400,7 @@ static long validate_slab_cache(struct kmem_cache *s) { int node; unsigned long count = 0; - unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->oo)) * + unsigned long *map = kmalloc(BITS_TO_LONGS(oo_objects(s->max)) * sizeof(unsigned long), GFP_KERNEL); if (!map) @@ -3676,22 +3700,23 @@ static int list_locations(struct kmem_cache *s, char *buf, } enum slab_stat_type { - SL_FULL, - SL_PARTIAL, - SL_CPU, - SL_OBJECTS + SL_ALL, /* All slabs */ + SL_PARTIAL, /* Only partially allocated slabs */ + SL_CPU, /* Only slabs used for cpu caches */ + SL_OBJECTS, /* Determine allocated objects not slabs */ + SL_TOTAL /* Determine object capacity not slabs */ }; -#define SO_FULL (1 << SL_FULL) +#define SO_ALL (1 << SL_ALL) #define SO_PARTIAL (1 << SL_PARTIAL) #define SO_CPU (1 << SL_CPU) #define SO_OBJECTS (1 << SL_OBJECTS) +#define SO_TOTAL (1 << SL_TOTAL) static ssize_t show_slab_objects(struct kmem_cache *s, char *buf, unsigned long flags) { unsigned long total = 0; - int cpu; int node; int x; unsigned long *nodes; @@ -3702,56 +3727,60 @@ static ssize_t show_slab_objects(struct kmem_cache *s, return -ENOMEM; per_cpu = nodes + nr_node_ids; - for_each_possible_cpu(cpu) { - struct page *page; - struct kmem_cache_cpu *c = get_cpu_slab(s, cpu); + if (flags & SO_CPU) { + int cpu; - if (!c) - continue; + for_each_possible_cpu(cpu) { + struct kmem_cache_cpu *c = get_cpu_slab(s, cpu); - page = c->page; - node = c->node; - if (node < 0) - continue; - if (page) { - if (flags & SO_CPU) { - if (flags & SO_OBJECTS) - x = page->inuse; + if (!c || c->node < 0) + continue; + + if (c->page) { + if (flags & SO_TOTAL) + x = c->page->objects; + else if (flags & SO_OBJECTS) + x = c->page->inuse; else x = 1; + total += x; - nodes[node] += x; + nodes[c->node] += x; } - per_cpu[node]++; + per_cpu[c->node]++; } } - for_each_node_state(node, N_NORMAL_MEMORY) { - struct kmem_cache_node *n = get_node(s, node); + if (flags & SO_ALL) { + for_each_node_state(node, N_NORMAL_MEMORY) { + struct kmem_cache_node *n = get_node(s, node); + + if (flags & SO_TOTAL) + x = atomic_long_read(&n->total_objects); + else if (flags & SO_OBJECTS) + x = atomic_long_read(&n->total_objects) - + count_partial(n, count_free); - if (flags & SO_PARTIAL) { - if (flags & SO_OBJECTS) - x = count_partial(n); else - x = n->nr_partial; + x = atomic_long_read(&n->nr_slabs); total += x; nodes[node] += x; } - if (flags & SO_FULL) { - int full_slabs = atomic_long_read(&n->nr_slabs) - - per_cpu[node] - - n->nr_partial; + } else if (flags & SO_PARTIAL) { + for_each_node_state(node, N_NORMAL_MEMORY) { + struct kmem_cache_node *n = get_node(s, node); - if (flags & SO_OBJECTS) - x = full_slabs * oo_objects(s->oo); + if (flags & SO_TOTAL) + x = count_partial(n, count_total); + else if (flags & SO_OBJECTS) + x = count_partial(n, count_inuse); else - x = full_slabs; + x = n->nr_partial; total += x; nodes[node] += x; } } - x = sprintf(buf, "%lu", total); #ifdef CONFIG_NUMA for_each_node_state(node, N_NORMAL_MEMORY) @@ -3852,7 +3881,7 @@ SLAB_ATTR_RO(aliases); static ssize_t slabs_show(struct kmem_cache *s, char *buf) { - return show_slab_objects(s, buf, SO_FULL|SO_PARTIAL|SO_CPU); + return show_slab_objects(s, buf, SO_ALL); } SLAB_ATTR_RO(slabs); @@ -3870,10 +3899,22 @@ SLAB_ATTR_RO(cpu_slabs); static ssize_t objects_show(struct kmem_cache *s, char *buf) { - return show_slab_objects(s, buf, SO_FULL|SO_PARTIAL|SO_CPU|SO_OBJECTS); + return show_slab_objects(s, buf, SO_ALL|SO_OBJECTS); } SLAB_ATTR_RO(objects); +static ssize_t objects_partial_show(struct kmem_cache *s, char *buf) +{ + return show_slab_objects(s, buf, SO_PARTIAL|SO_OBJECTS); +} +SLAB_ATTR_RO(objects_partial); + +static ssize_t total_objects_show(struct kmem_cache *s, char *buf) +{ + return show_slab_objects(s, buf, SO_ALL|SO_TOTAL); +} +SLAB_ATTR_RO(total_objects); + static ssize_t sanity_checks_show(struct kmem_cache *s, char *buf) { return sprintf(buf, "%d\n", !!(s->flags & SLAB_DEBUG_FREE)); @@ -4131,6 +4172,8 @@ static struct attribute *slab_attrs[] = { &objs_per_slab_attr.attr, &order_attr.attr, &objects_attr.attr, + &objects_partial_attr.attr, + &total_objects_attr.attr, &slabs_attr.attr, &partial_attr.attr, &cpu_slabs_attr.attr, @@ -4459,7 +4502,8 @@ static int s_show(struct seq_file *m, void *p) unsigned long nr_partials = 0; unsigned long nr_slabs = 0; unsigned long nr_inuse = 0; - unsigned long nr_objs; + unsigned long nr_objs = 0; + unsigned long nr_free = 0; struct kmem_cache *s; int node; @@ -4473,11 +4517,11 @@ static int s_show(struct seq_file *m, void *p) nr_partials += n->nr_partial; nr_slabs += atomic_long_read(&n->nr_slabs); - nr_inuse += count_partial(n); + nr_objs += atomic_long_read(&n->total_objects); + nr_free += count_partial(n, count_free); } - nr_objs = nr_slabs * oo_objects(s->oo); - nr_inuse += (nr_slabs - nr_partials) * oo_objects(s->oo); + nr_inuse = nr_objs - nr_free; seq_printf(m, "%-17s %6lu %6lu %6u %4u %4d", s->name, nr_inuse, nr_objs, s->size, oo_objects(s->oo), -- cgit v1.2.3 From e275ac477161a3df5c27e40c55f7af94cfb396cf Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 28 Apr 2008 02:11:56 -0700 Subject: kerneldoc for Add to the generated kerneldoc, with some overview to go along with those per-function descriptions. Signed-off-by: David Brownell Cc: Russell King Cc: Alessandro Zummo Cc: "Randy.Dunlap" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/DocBook/kernel-api.tmpl | 54 +++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) (limited to 'Documentation') diff --git a/Documentation/DocBook/kernel-api.tmpl b/Documentation/DocBook/kernel-api.tmpl index 488dd4a4945b..617c2d979975 100644 --- a/Documentation/DocBook/kernel-api.tmpl +++ b/Documentation/DocBook/kernel-api.tmpl @@ -645,4 +645,58 @@ X!Idrivers/video/console/fonts.c !Edrivers/i2c/i2c-core.c + + Clock Framework + + + The clock framework defines programming interfaces to support + software management of the system clock tree. + This framework is widely used with System-On-Chip (SOC) platforms + to support power management and various devices which may need + custom clock rates. + Note that these "clocks" don't relate to timekeeping or real + time clocks (RTCs), each of which have separate frameworks. + These struct clk instances may be used + to manage for example a 96 MHz signal that is used to shift bits + into and out of peripherals or busses, or otherwise trigger + synchronous state machine transitions in system hardware. + + + + Power management is supported by explicit software clock gating: + unused clocks are disabled, so the system doesn't waste power + changing the state of transistors that aren't in active use. + On some systems this may be backed by hardware clock gating, + where clocks are gated without being disabled in software. + Sections of chips that are powered but not clocked may be able + to retain their last state. + This low power state is often called a retention + mode. + This mode still incurs leakage currents, especially with finer + circuit geometries, but for CMOS circuits power is mostly used + by clocked state changes. + + + + Power-aware drivers only enable their clocks when the device + they manage is in active use. Also, system sleep states often + differ according to which clock domains are active: while a + "standby" state may allow wakeup from several active domains, a + "mem" (suspend-to-RAM) state may require a more wholesale shutdown + of clocks derived from higher speed PLLs and oscillators, limiting + the number of possible wakeup event sources. A driver's suspend + method may need to be aware of system-specific clock constraints + on the target sleep state. + + + + Some platforms support programmable clock generators. These + can be used by external chips of various kinds, such as other + CPUs, multimedia codecs, and devices with strict requirements + for interface clocking. + + +!Iinclude/linux/clk.h + + -- cgit v1.2.3 From 3c18ddd160d1fcd46d1131d9ad6c594dd8e9af99 Mon Sep 17 00:00:00 2001 From: Nick Piggin Date: Mon, 28 Apr 2008 02:12:10 -0700 Subject: mm: remove nopage Nothing in the tree uses nopage any more. Remove support for it in the core mm code and documentation (and a few stray references to it in comments). Signed-off-by: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/feature-removal-schedule.txt | 9 --------- Documentation/filesystems/Locking | 3 --- drivers/media/video/vino.c | 2 +- drivers/video/vermilion/vermilion.c | 5 +++-- fs/gfs2/ops_address.c | 2 +- include/linux/mm.h | 8 -------- mm/memory.c | 22 +++++----------------- mm/mincore.c | 2 +- mm/rmap.c | 1 - 9 files changed, 11 insertions(+), 43 deletions(-) (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 448729fcaeb1..599fe55bf297 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -128,15 +128,6 @@ Who: Arjan van de Ven --------------------------- -What: vm_ops.nopage -When: Soon, provided in-kernel callers have been converted -Why: This interface is replaced by vm_ops.fault, but it has been around - forever, is used by a lot of drivers, and doesn't cost much to - maintain. -Who: Nick Piggin - ---------------------------- - What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment When: October 2008 Why: The stacking of class devices makes these values misleading and diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 42d4b30b1045..c2992bc54f2f 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -511,7 +511,6 @@ prototypes: void (*open)(struct vm_area_struct*); void (*close)(struct vm_area_struct*); int (*fault)(struct vm_area_struct*, struct vm_fault *); - struct page *(*nopage)(struct vm_area_struct*, unsigned long, int *); int (*page_mkwrite)(struct vm_area_struct *, struct page *); locking rules: @@ -519,7 +518,6 @@ locking rules: open: no yes close: no yes fault: no yes -nopage: no yes page_mkwrite: no yes no ->page_mkwrite() is called when a previously read-only page is @@ -537,4 +535,3 @@ NULL. ipc/shm.c::shm_delete() - may need BKL. ->read() and ->write() in many drivers are (probably) missing BKL. -drivers/sgi/char/graphics.c::sgi_graphics_nopage() - may need BKL. diff --git a/drivers/media/video/vino.c b/drivers/media/video/vino.c index d545c98dd5e7..01ea99c9bc1a 100644 --- a/drivers/media/video/vino.c +++ b/drivers/media/video/vino.c @@ -13,7 +13,7 @@ /* * TODO: * - remove "mark pages reserved-hacks" from memory allocation code - * and implement nopage() + * and implement fault() * - check decimation, calculating and reporting image size when * using decimation * - implement read(), user mode buffers and overlay (?) diff --git a/drivers/video/vermilion/vermilion.c b/drivers/video/vermilion/vermilion.c index 2aa71eb67c2b..c18f1884b550 100644 --- a/drivers/video/vermilion/vermilion.c +++ b/drivers/video/vermilion/vermilion.c @@ -112,8 +112,9 @@ static int vmlfb_alloc_vram_area(struct vram_area *va, unsigned max_order, /* * It seems like __get_free_pages only ups the usage count - * of the first page. This doesn't work with nopage mapping, so - * up the usage count once more. + * of the first page. This doesn't work with fault mapping, so + * up the usage count once more (XXX: should use split_page or + * compound page). */ memset((void *)va->logical, 0x00, va->size); diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 90a04a6e3789..f55394e57cb2 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -438,7 +438,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page) int error; /* - * Due to the order of unstuffing files and ->nopage(), we can be + * Due to the order of unstuffing files and ->fault(), we can be * asked for a zero page in the case of a stuffed file being extended, * so we need to supply one here. It doesn't happen often. */ diff --git a/include/linux/mm.h b/include/linux/mm.h index 286d31521605..ca973359fe5f 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h @@ -164,8 +164,6 @@ struct vm_operations_struct { void (*open)(struct vm_area_struct * area); void (*close)(struct vm_area_struct * area); int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf); - struct page *(*nopage)(struct vm_area_struct *area, - unsigned long address, int *type); unsigned long (*nopfn)(struct vm_area_struct *area, unsigned long address); @@ -648,12 +646,6 @@ static inline int page_mapped(struct page *page) return atomic_read(&(page)->_mapcount) >= 0; } -/* - * Error return values for the *_nopage functions - */ -#define NOPAGE_SIGBUS (NULL) -#define NOPAGE_OOM ((struct page *) (-1)) - /* * Error return values for the *_nopfn functions */ diff --git a/mm/memory.c b/mm/memory.c index 0d14d1e58a5f..46958fb97c2d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1057,8 +1057,7 @@ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, if (pages) foll_flags |= FOLL_GET; if (!write && !(vma->vm_flags & VM_LOCKED) && - (!vma->vm_ops || (!vma->vm_ops->nopage && - !vma->vm_ops->fault))) + (!vma->vm_ops || !vma->vm_ops->fault)) foll_flags |= FOLL_ANON; do { @@ -2199,20 +2198,9 @@ static int __do_fault(struct mm_struct *mm, struct vm_area_struct *vma, BUG_ON(vma->vm_flags & VM_PFNMAP); - if (likely(vma->vm_ops->fault)) { - ret = vma->vm_ops->fault(vma, &vmf); - if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) - return ret; - } else { - /* Legacy ->nopage path */ - ret = 0; - vmf.page = vma->vm_ops->nopage(vma, address & PAGE_MASK, &ret); - /* no page was available -- either SIGBUS or OOM */ - if (unlikely(vmf.page == NOPAGE_SIGBUS)) - return VM_FAULT_SIGBUS; - else if (unlikely(vmf.page == NOPAGE_OOM)) - return VM_FAULT_OOM; - } + ret = vma->vm_ops->fault(vma, &vmf); + if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE))) + return ret; /* * For consistency in subsequent calls, make the faulted page always @@ -2458,7 +2446,7 @@ static inline int handle_pte_fault(struct mm_struct *mm, if (!pte_present(entry)) { if (pte_none(entry)) { if (vma->vm_ops) { - if (vma->vm_ops->fault || vma->vm_ops->nopage) + if (likely(vma->vm_ops->fault)) return do_linear_fault(mm, vma, address, pte, pmd, write_access, entry); if (unlikely(vma->vm_ops->nopfn)) diff --git a/mm/mincore.c b/mm/mincore.c index 5efe0ded69b1..5178800bc129 100644 --- a/mm/mincore.c +++ b/mm/mincore.c @@ -33,7 +33,7 @@ static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff) * When tmpfs swaps out a page from a file, any process mapping that * file will not get a swp_entry_t in its pte, but rather it is like * any other file mapping (ie. marked !present and faulted in with - * tmpfs's .nopage). So swapped out tmpfs mappings are tested here. + * tmpfs's .fault). So swapped out tmpfs mappings are tested here. * * However when tmpfs moves the page from pagecache and into swapcache, * it is still in core, but the find_get_page below won't find it. diff --git a/mm/rmap.c b/mm/rmap.c index e9bb6b1093f6..bf0a5b7cfb8e 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -662,7 +662,6 @@ void page_remove_rmap(struct page *page, struct vm_area_struct *vma) printk (KERN_EMERG " page->mapping = %p\n", page->mapping); print_symbol (KERN_EMERG " vma->vm_ops = %s\n", (unsigned long)vma->vm_ops); if (vma->vm_ops) { - print_symbol (KERN_EMERG " vma->vm_ops->nopage = %s\n", (unsigned long)vma->vm_ops->nopage); print_symbol (KERN_EMERG " vma->vm_ops->fault = %s\n", (unsigned long)vma->vm_ops->fault); } if (vma->vm_file && vma->vm_file->f_op) -- cgit v1.2.3 From 19770b32609b6bf97a3dece2529089494cbfc549 Mon Sep 17 00:00:00 2001 From: Mel Gorman Date: Mon, 28 Apr 2008 02:12:18 -0700 Subject: mm: filter based on a nodemask as well as a gfp_mask The MPOL_BIND policy creates a zonelist that is used for allocations controlled by that mempolicy. As the per-node zonelist is already being filtered based on a zone id, this patch adds a version of __alloc_pages() that takes a nodemask for further filtering. This eliminates the need for MPOL_BIND to create a custom zonelist. A positive benefit of this is that allocations using MPOL_BIND now use the local node's distance-ordered zonelist instead of a custom node-id-ordered zonelist. I.e., pages will be allocated from the closest allowed node with available memory. [Lee.Schermerhorn@hp.com: Mempolicy: update stale documentation and comments] [Lee.Schermerhorn@hp.com: Mempolicy: make dequeue_huge_page_vma() obey MPOL_BIND nodemask] [Lee.Schermerhorn@hp.com: Mempolicy: make dequeue_huge_page_vma() obey MPOL_BIND nodemask rework] Signed-off-by: Mel Gorman Acked-by: Christoph Lameter Signed-off-by: Lee Schermerhorn Cc: KAMEZAWA Hiroyuki Cc: Mel Gorman Cc: Hugh Dickins Cc: Nick Piggin Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/numa_memory_policy.txt | 11 +- fs/buffer.c | 9 +- include/linux/cpuset.h | 4 +- include/linux/gfp.h | 4 + include/linux/mempolicy.h | 19 ++-- include/linux/mmzone.h | 80 ++++++++------ kernel/cpuset.c | 18 +--- mm/hugetlb.c | 6 +- mm/mempolicy.c | 184 +++++++++++++------------------- mm/mmzone.c | 30 ++++++ mm/page_alloc.c | 50 ++++++--- 11 files changed, 224 insertions(+), 191 deletions(-) (limited to 'Documentation') diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index dd4986497996..1278e685d650 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt @@ -182,14 +182,9 @@ Components of Memory Policies The Default mode does not use the optional set of nodes. MPOL_BIND: This mode specifies that memory must come from the - set of nodes specified by the policy. - - The memory policy APIs do not specify an order in which the nodes - will be searched. However, unlike "local allocation", the Bind - policy does not consider the distance between the nodes. Rather, - allocations will fallback to the nodes specified by the policy in - order of numeric node id. Like everything in Linux, this is subject - to change. + set of nodes specified by the policy. Memory will be allocated from + the node in the set with sufficient free memory that is closest to + the node where the allocation takes place. MPOL_PREFERRED: This mode specifies that the allocation should be attempted from the single node specified in the policy. If that diff --git a/fs/buffer.c b/fs/buffer.c index ac84cd13075d..7d51e649b19a 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -360,16 +360,17 @@ void invalidate_bdev(struct block_device *bdev) */ static void free_more_memory(void) { - struct zoneref *zrefs; + struct zone *zone; int nid; wakeup_pdflush(1024); yield(); for_each_online_node(nid) { - zrefs = first_zones_zonelist(node_zonelist(nid, GFP_NOFS), - gfp_zone(GFP_NOFS)); - if (zrefs->zone) + (void)first_zones_zonelist(node_zonelist(nid, GFP_NOFS), + gfp_zone(GFP_NOFS), NULL, + &zone); + if (zone) try_to_free_pages(node_zonelist(nid, GFP_NOFS), 0, GFP_NOFS); } diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index 726761e24003..038578362b47 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -26,7 +26,7 @@ extern nodemask_t cpuset_mems_allowed(struct task_struct *p); #define cpuset_current_mems_allowed (current->mems_allowed) void cpuset_init_current_mems_allowed(void); void cpuset_update_task_memory_state(void); -int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl); +int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask); extern int __cpuset_zone_allowed_softwall(struct zone *z, gfp_t gfp_mask); extern int __cpuset_zone_allowed_hardwall(struct zone *z, gfp_t gfp_mask); @@ -103,7 +103,7 @@ static inline nodemask_t cpuset_mems_allowed(struct task_struct *p) static inline void cpuset_init_current_mems_allowed(void) {} static inline void cpuset_update_task_memory_state(void) {} -static inline int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl) +static inline int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask) { return 1; } diff --git a/include/linux/gfp.h b/include/linux/gfp.h index e1c6064cb6c7..898aa9d5b6c2 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h @@ -182,6 +182,10 @@ static inline void arch_alloc_page(struct page *page, int order) { } extern struct page *__alloc_pages(gfp_t, unsigned int, struct zonelist *); +extern struct page * +__alloc_pages_nodemask(gfp_t, unsigned int, + struct zonelist *, nodemask_t *nodemask); + static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order) { diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 69160dc32d48..b8b3da7a3315 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -54,19 +54,20 @@ struct mm_struct; * mmap_sem. * * Freeing policy: - * When policy is MPOL_BIND v.zonelist is kmalloc'ed and must be kfree'd. - * All other policies don't have any external state. mpol_free() handles this. + * Mempolicy objects are reference counted. A mempolicy will be freed when + * mpol_free() decrements the reference count to zero. * * Copying policy objects: - * For MPOL_BIND the zonelist must be always duplicated. mpol_clone() does this. + * mpol_copy() allocates a new mempolicy and copies the specified mempolicy + * to the new storage. The reference count of the new object is initialized + * to 1, representing the caller of mpol_copy(). */ struct mempolicy { atomic_t refcnt; short policy; /* See MPOL_* above */ union { - struct zonelist *zonelist; /* bind */ short preferred_node; /* preferred */ - nodemask_t nodes; /* interleave */ + nodemask_t nodes; /* interleave/bind */ /* undefined for default */ } v; nodemask_t cpuset_mems_allowed; /* mempolicy relative to these nodes */ @@ -151,7 +152,8 @@ extern void mpol_fix_fork_child_flag(struct task_struct *p); extern struct mempolicy default_policy; extern struct zonelist *huge_zonelist(struct vm_area_struct *vma, - unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol); + unsigned long addr, gfp_t gfp_flags, + struct mempolicy **mpol, nodemask_t **nodemask); extern unsigned slab_node(struct mempolicy *policy); extern enum zone_type policy_zone; @@ -239,8 +241,11 @@ static inline void mpol_fix_fork_child_flag(struct task_struct *p) } static inline struct zonelist *huge_zonelist(struct vm_area_struct *vma, - unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol) + unsigned long addr, gfp_t gfp_flags, + struct mempolicy **mpol, nodemask_t **nodemask) { + *mpol = NULL; + *nodemask = NULL; return node_zonelist(0, gfp_flags); } diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index d34b4c290017..498d6ceff2f4 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h @@ -749,36 +749,60 @@ static inline int zonelist_node_idx(struct zoneref *zoneref) #endif /* CONFIG_NUMA */ } -static inline void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref) -{ - zoneref->zone = zone; - zoneref->zone_idx = zone_idx(zone); -} +/** + * next_zones_zonelist - Returns the next zone at or below highest_zoneidx within the allowed nodemask using a cursor within a zonelist as a starting point + * @z - The cursor used as a starting point for the search + * @highest_zoneidx - The zone index of the highest zone to return + * @nodes - An optional nodemask to filter the zonelist with + * @zone - The first suitable zone found is returned via this parameter + * + * This function returns the next zone at or below a given zone index that is + * within the allowed nodemask using a cursor as the starting point for the + * search. The zoneref returned is a cursor that is used as the next starting + * point for future calls to next_zones_zonelist(). + */ +struct zoneref *next_zones_zonelist(struct zoneref *z, + enum zone_type highest_zoneidx, + nodemask_t *nodes, + struct zone **zone); -/* Returns the first zone at or below highest_zoneidx in a zonelist */ +/** + * first_zones_zonelist - Returns the first zone at or below highest_zoneidx within the allowed nodemask in a zonelist + * @zonelist - The zonelist to search for a suitable zone + * @highest_zoneidx - The zone index of the highest zone to return + * @nodes - An optional nodemask to filter the zonelist with + * @zone - The first suitable zone found is returned via this parameter + * + * This function returns the first zone at or below a given zone index that is + * within the allowed nodemask. The zoneref returned is a cursor that can be + * used to iterate the zonelist with next_zones_zonelist. The cursor should + * not be used by the caller as it does not match the value of the zone + * returned. + */ static inline struct zoneref *first_zones_zonelist(struct zonelist *zonelist, - enum zone_type highest_zoneidx) + enum zone_type highest_zoneidx, + nodemask_t *nodes, + struct zone **zone) { - struct zoneref *z; - - /* Find the first suitable zone to use for the allocation */ - z = zonelist->_zonerefs; - while (zonelist_zone_idx(z) > highest_zoneidx) - z++; - - return z; + return next_zones_zonelist(zonelist->_zonerefs, highest_zoneidx, nodes, + zone); } -/* Returns the next zone at or below highest_zoneidx in a zonelist */ -static inline struct zoneref *next_zones_zonelist(struct zoneref *z, - enum zone_type highest_zoneidx) -{ - /* Find the next suitable zone to use for the allocation */ - while (zonelist_zone_idx(z) > highest_zoneidx) - z++; - - return z; -} +/** + * for_each_zone_zonelist_nodemask - helper macro to iterate over valid zones in a zonelist at or below a given zone index and within a nodemask + * @zone - The current zone in the iterator + * @z - The current pointer within zonelist->zones being iterated + * @zlist - The zonelist being iterated + * @highidx - The zone index of the highest zone to return + * @nodemask - Nodemask allowed by the allocator + * + * This iterator iterates though all zones at or below a given zone index and + * within a given nodemask + */ +#define for_each_zone_zonelist_nodemask(zone, z, zlist, highidx, nodemask) \ + for (z = first_zones_zonelist(zlist, highidx, nodemask, &zone); \ + zone; \ + z = next_zones_zonelist(z, highidx, nodemask, &zone)) \ /** * for_each_zone_zonelist - helper macro to iterate over valid zones in a zonelist at or below a given zone index @@ -790,11 +814,7 @@ static inline struct zoneref *next_zones_zonelist(struct zoneref *z, * This iterator iterates though all zones at or below a given zone index. */ #define for_each_zone_zonelist(zone, z, zlist, highidx) \ - for (z = first_zones_zonelist(zlist, highidx), \ - zone = zonelist_zone(z++); \ - zone; \ - z = next_zones_zonelist(z, highidx), \ - zone = zonelist_zone(z++)) + for_each_zone_zonelist_nodemask(zone, z, zlist, highidx, NULL) #ifdef CONFIG_SPARSEMEM #include diff --git a/kernel/cpuset.c b/kernel/cpuset.c index a220b13cbfaf..c9923e3c9a3b 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c @@ -1958,22 +1958,14 @@ nodemask_t cpuset_mems_allowed(struct task_struct *tsk) } /** - * cpuset_zonelist_valid_mems_allowed - check zonelist vs. curremt mems_allowed - * @zl: the zonelist to be checked + * cpuset_nodemask_valid_mems_allowed - check nodemask vs. curremt mems_allowed + * @nodemask: the nodemask to be checked * - * Are any of the nodes on zonelist zl allowed in current->mems_allowed? + * Are any of the nodes in the nodemask allowed in current->mems_allowed? */ -int cpuset_zonelist_valid_mems_allowed(struct zonelist *zl) +int cpuset_nodemask_valid_mems_allowed(nodemask_t *nodemask) { - int i; - - for (i = 0; zl->_zonerefs[i].zone; i++) { - int nid = zonelist_node_idx(&zl->_zonerefs[i]); - - if (node_isset(nid, current->mems_allowed)) - return 1; - } - return 0; + return nodes_intersects(*nodemask, current->mems_allowed); } /* diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 4bced0d705ca..3737d82f5225 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -95,12 +95,14 @@ static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma, int nid; struct page *page = NULL; struct mempolicy *mpol; + nodemask_t *nodemask; struct zonelist *zonelist = huge_zonelist(vma, address, - htlb_alloc_mask, &mpol); + htlb_alloc_mask, &mpol, &nodemask); struct zone *zone; struct zoneref *z; - for_each_zone_zonelist(zone, z, zonelist, MAX_NR_ZONES - 1) { + for_each_zone_zonelist_nodemask(zone, z, zonelist, + MAX_NR_ZONES - 1, nodemask) { nid = zone_to_nid(zone); if (cpuset_zone_allowed_softwall(zone, htlb_alloc_mask) && !list_empty(&hugepage_freelists[nid])) { diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 90193a2a915b..acb5ee3587c3 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -163,42 +163,25 @@ static int mpol_check_policy(int mode, nodemask_t *nodes) return 0; } -/* Generate a custom zonelist for the BIND policy. */ -static struct zonelist *bind_zonelist(nodemask_t *nodes) +/* Check that the nodemask contains at least one populated zone */ +static int is_valid_nodemask(nodemask_t *nodemask) { - struct zonelist *zl; - int num, max, nd; - enum zone_type k; + int nd, k; - max = 1 + MAX_NR_ZONES * nodes_weight(*nodes); - max++; /* space for zlcache_ptr (see mmzone.h) */ - zl = kmalloc(sizeof(struct zone *) * max, GFP_KERNEL); - if (!zl) - return ERR_PTR(-ENOMEM); - zl->zlcache_ptr = NULL; - num = 0; - /* First put in the highest zones from all nodes, then all the next - lower zones etc. Avoid empty zones because the memory allocator - doesn't like them. If you implement node hot removal you - have to fix that. */ - k = MAX_NR_ZONES - 1; - while (1) { - for_each_node_mask(nd, *nodes) { - struct zone *z = &NODE_DATA(nd)->node_zones[k]; - if (z->present_pages > 0) - zoneref_set_zone(z, &zl->_zonerefs[num++]); + /* Check that there is something useful in this mask */ + k = policy_zone; + + for_each_node_mask(nd, *nodemask) { + struct zone *z; + + for (k = 0; k <= policy_zone; k++) { + z = &NODE_DATA(nd)->node_zones[k]; + if (z->present_pages > 0) + return 1; } - if (k == 0) - break; - k--; - } - if (num == 0) { - kfree(zl); - return ERR_PTR(-EINVAL); } - zl->_zonerefs[num].zone = NULL; - zl->_zonerefs[num].zone_idx = 0; - return zl; + + return 0; } /* Create a new policy */ @@ -229,12 +212,11 @@ static struct mempolicy *mpol_new(int mode, nodemask_t *nodes) policy->v.preferred_node = -1; break; case MPOL_BIND: - policy->v.zonelist = bind_zonelist(nodes); - if (IS_ERR(policy->v.zonelist)) { - void *error_code = policy->v.zonelist; + if (!is_valid_nodemask(nodes)) { kmem_cache_free(policy_cache, policy); - return error_code; + return ERR_PTR(-EINVAL); } + policy->v.nodes = *nodes; break; } policy->policy = mode; @@ -500,19 +482,12 @@ static long do_set_mempolicy(int mode, nodemask_t *nodes) /* Fill a zone bitmap for a policy */ static void get_zonemask(struct mempolicy *p, nodemask_t *nodes) { - int i; - nodes_clear(*nodes); switch (p->policy) { - case MPOL_BIND: - for (i = 0; p->v.zonelist->_zonerefs[i].zone; i++) { - struct zoneref *zref; - zref = &p->v.zonelist->_zonerefs[i]; - node_set(zonelist_node_idx(zref), *nodes); - } - break; case MPOL_DEFAULT: break; + case MPOL_BIND: + /* Fall through */ case MPOL_INTERLEAVE: *nodes = p->v.nodes; break; @@ -1160,6 +1135,18 @@ static struct mempolicy * get_vma_policy(struct task_struct *task, return pol; } +/* Return a nodemask representing a mempolicy */ +static nodemask_t *nodemask_policy(gfp_t gfp, struct mempolicy *policy) +{ + /* Lower zones don't get a nodemask applied for MPOL_BIND */ + if (unlikely(policy->policy == MPOL_BIND) && + gfp_zone(gfp) >= policy_zone && + cpuset_nodemask_valid_mems_allowed(&policy->v.nodes)) + return &policy->v.nodes; + + return NULL; +} + /* Return a zonelist representing a mempolicy */ static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy) { @@ -1172,12 +1159,17 @@ static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy) nd = numa_node_id(); break; case MPOL_BIND: - /* Lower zones don't get a policy applied */ - /* Careful: current->mems_allowed might have moved */ - if (gfp_zone(gfp) >= policy_zone) - if (cpuset_zonelist_valid_mems_allowed(policy->v.zonelist)) - return policy->v.zonelist; - /*FALL THROUGH*/ + /* + * Normally, MPOL_BIND allocations node-local are node-local + * within the allowed nodemask. However, if __GFP_THISNODE is + * set and the current node is part of the mask, we use the + * the zonelist for the first node in the mask instead. + */ + nd = numa_node_id(); + if (unlikely(gfp & __GFP_THISNODE) && + unlikely(!node_isset(nd, policy->v.nodes))) + nd = first_node(policy->v.nodes); + break; case MPOL_INTERLEAVE: /* should not happen */ case MPOL_DEFAULT: nd = numa_node_id(); @@ -1220,7 +1212,14 @@ unsigned slab_node(struct mempolicy *policy) * Follow bind policy behavior and start allocation at the * first node. */ - return zonelist_node_idx(policy->v.zonelist->_zonerefs); + struct zonelist *zonelist; + struct zone *zone; + enum zone_type highest_zoneidx = gfp_zone(GFP_KERNEL); + zonelist = &NODE_DATA(numa_node_id())->node_zonelists[0]; + (void)first_zones_zonelist(zonelist, highest_zoneidx, + &policy->v.nodes, + &zone); + return zone->node; } case MPOL_PREFERRED: @@ -1278,25 +1277,31 @@ static inline unsigned interleave_nid(struct mempolicy *pol, * @vma = virtual memory area whose policy is sought * @addr = address in @vma for shared policy lookup and interleave policy * @gfp_flags = for requested zone - * @mpol = pointer to mempolicy pointer for reference counted 'BIND policy + * @mpol = pointer to mempolicy pointer for reference counted mempolicy + * @nodemask = pointer to nodemask pointer for MPOL_BIND nodemask * * Returns a zonelist suitable for a huge page allocation. - * If the effective policy is 'BIND, returns pointer to policy's zonelist. + * If the effective policy is 'BIND, returns pointer to local node's zonelist, + * and a pointer to the mempolicy's @nodemask for filtering the zonelist. * If it is also a policy for which get_vma_policy() returns an extra - * reference, we must hold that reference until after allocation. + * reference, we must hold that reference until after the allocation. * In that case, return policy via @mpol so hugetlb allocation can drop - * the reference. For non-'BIND referenced policies, we can/do drop the + * the reference. For non-'BIND referenced policies, we can/do drop the * reference here, so the caller doesn't need to know about the special case * for default and current task policy. */ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, - gfp_t gfp_flags, struct mempolicy **mpol) + gfp_t gfp_flags, struct mempolicy **mpol, + nodemask_t **nodemask) { struct mempolicy *pol = get_vma_policy(current, vma, addr); struct zonelist *zl; *mpol = NULL; /* probably no unref needed */ - if (pol->policy == MPOL_INTERLEAVE) { + *nodemask = NULL; /* assume !MPOL_BIND */ + if (pol->policy == MPOL_BIND) { + *nodemask = &pol->v.nodes; + } else if (pol->policy == MPOL_INTERLEAVE) { unsigned nid; nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); @@ -1376,14 +1381,15 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) /* * slow path: ref counted policy -- shared or vma */ - struct page *page = __alloc_pages(gfp, 0, zl); + struct page *page = __alloc_pages_nodemask(gfp, 0, + zl, nodemask_policy(gfp, pol)); __mpol_free(pol); return page; } /* * fast path: default or task policy */ - return __alloc_pages(gfp, 0, zl); + return __alloc_pages_nodemask(gfp, 0, zl, nodemask_policy(gfp, pol)); } /** @@ -1415,7 +1421,8 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order) pol = &default_policy; if (pol->policy == MPOL_INTERLEAVE) return alloc_page_interleave(gfp, order, interleave_nodes(pol)); - return __alloc_pages(gfp, order, zonelist_policy(gfp, pol)); + return __alloc_pages_nodemask(gfp, order, + zonelist_policy(gfp, pol), nodemask_policy(gfp, pol)); } EXPORT_SYMBOL(alloc_pages_current); @@ -1440,14 +1447,6 @@ struct mempolicy *__mpol_copy(struct mempolicy *old) } *new = *old; atomic_set(&new->refcnt, 1); - if (new->policy == MPOL_BIND) { - int sz = ksize(old->v.zonelist); - new->v.zonelist = kmemdup(old->v.zonelist, sz, GFP_KERNEL); - if (!new->v.zonelist) { - kmem_cache_free(policy_cache, new); - return ERR_PTR(-ENOMEM); - } - } return new; } @@ -1461,21 +1460,12 @@ int __mpol_equal(struct mempolicy *a, struct mempolicy *b) switch (a->policy) { case MPOL_DEFAULT: return 1; + case MPOL_BIND: + /* Fall through */ case MPOL_INTERLEAVE: return nodes_equal(a->v.nodes, b->v.nodes); case MPOL_PREFERRED: return a->v.preferred_node == b->v.preferred_node; - case MPOL_BIND: { - int i; - for (i = 0; a->v.zonelist->_zonerefs[i].zone; i++) { - struct zone *za, *zb; - za = zonelist_zone(&a->v.zonelist->_zonerefs[i]); - zb = zonelist_zone(&b->v.zonelist->_zonerefs[i]); - if (za != zb) - return 0; - } - return b->v.zonelist->_zonerefs[i].zone == NULL; - } default: BUG(); return 0; @@ -1487,8 +1477,6 @@ void __mpol_free(struct mempolicy *p) { if (!atomic_dec_and_test(&p->refcnt)) return; - if (p->policy == MPOL_BIND) - kfree(p->v.zonelist); p->policy = MPOL_DEFAULT; kmem_cache_free(policy_cache, p); } @@ -1779,6 +1767,8 @@ static void mpol_rebind_policy(struct mempolicy *pol, switch (pol->policy) { case MPOL_DEFAULT: break; + case MPOL_BIND: + /* Fall through */ case MPOL_INTERLEAVE: nodes_remap(tmp, pol->v.nodes, *mpolmask, *newmask); pol->v.nodes = tmp; @@ -1791,32 +1781,6 @@ static void mpol_rebind_policy(struct mempolicy *pol, *mpolmask, *newmask); *mpolmask = *newmask; break; - case MPOL_BIND: { - nodemask_t nodes; - struct zoneref *z; - struct zonelist *zonelist; - - nodes_clear(nodes); - for (z = pol->v.zonelist->_zonerefs; z->zone; z++) - node_set(zonelist_node_idx(z), nodes); - nodes_remap(tmp, nodes, *mpolmask, *newmask); - nodes = tmp; - - zonelist = bind_zonelist(&nodes); - - /* If no mem, then zonelist is NULL and we keep old zonelist. - * If that old zonelist has no remaining mems_allowed nodes, - * then zonelist_policy() will "FALL THROUGH" to MPOL_DEFAULT. - */ - - if (!IS_ERR(zonelist)) { - /* Good - got mem - substitute new zonelist */ - kfree(pol->v.zonelist); - pol->v.zonelist = zonelist; - } - *mpolmask = *newmask; - break; - } default: BUG(); break; @@ -1879,9 +1843,7 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) break; case MPOL_BIND: - get_zonemask(pol, &nodes); - break; - + /* Fall through */ case MPOL_INTERLEAVE: nodes = pol->v.nodes; break; diff --git a/mm/mmzone.c b/mm/mmzone.c index eb5838634f18..486ed595ee6f 100644 --- a/mm/mmzone.c +++ b/mm/mmzone.c @@ -42,3 +42,33 @@ struct zone *next_zone(struct zone *zone) return zone; } +static inline int zref_in_nodemask(struct zoneref *zref, nodemask_t *nodes) +{ +#ifdef CONFIG_NUMA + return node_isset(zonelist_node_idx(zref), *nodes); +#else + return 1; +#endif /* CONFIG_NUMA */ +} + +/* Returns the next zone at or below highest_zoneidx in a zonelist */ +struct zoneref *next_zones_zonelist(struct zoneref *z, + enum zone_type highest_zoneidx, + nodemask_t *nodes, + struct zone **zone) +{ + /* + * Find the next suitable zone to use for the allocation. + * Only filter based on nodemask if it's set + */ + if (likely(nodes == NULL)) + while (zonelist_zone_idx(z) > highest_zoneidx) + z++; + else + while (zonelist_zone_idx(z) > highest_zoneidx || + (z->zone && !zref_in_nodemask(z, nodes))) + z++; + + *zone = zonelist_zone(z++); + return z; +} diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6d94d04ea784..b4beb3eea8b7 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -1377,7 +1377,7 @@ static void zlc_mark_zone_full(struct zonelist *zonelist, struct zoneref *z) * a page. */ static struct page * -get_page_from_freelist(gfp_t gfp_mask, unsigned int order, +get_page_from_freelist(gfp_t gfp_mask, nodemask_t *nodemask, unsigned int order, struct zonelist *zonelist, int high_zoneidx, int alloc_flags) { struct zoneref *z; @@ -1388,16 +1388,17 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, int zlc_active = 0; /* set if using zonelist_cache */ int did_zlc_setup = 0; /* just call zlc_setup() one time */ - z = first_zones_zonelist(zonelist, high_zoneidx); - classzone_idx = zonelist_zone_idx(z); - preferred_zone = zonelist_zone(z); + (void)first_zones_zonelist(zonelist, high_zoneidx, nodemask, + &preferred_zone); + classzone_idx = zone_idx(preferred_zone); zonelist_scan: /* * Scan zonelist, looking for a zone with enough free. * See also cpuset_zone_allowed() comment in kernel/cpuset.c. */ - for_each_zone_zonelist(zone, z, zonelist, high_zoneidx) { + for_each_zone_zonelist_nodemask(zone, z, zonelist, + high_zoneidx, nodemask) { if (NUMA_BUILD && zlc_active && !zlc_zone_worth_trying(zonelist, z, allowednodes)) continue; @@ -1447,9 +1448,9 @@ try_next_zone: /* * This is the 'heart' of the zoned buddy allocator. */ -struct page * -__alloc_pages(gfp_t gfp_mask, unsigned int order, - struct zonelist *zonelist) +static struct page * +__alloc_pages_internal(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, nodemask_t *nodemask) { const gfp_t wait = gfp_mask & __GFP_WAIT; enum zone_type high_zoneidx = gfp_zone(gfp_mask); @@ -1478,7 +1479,7 @@ restart: return NULL; } - page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order, + page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order, zonelist, high_zoneidx, ALLOC_WMARK_LOW|ALLOC_CPUSET); if (page) goto got_pg; @@ -1523,7 +1524,7 @@ restart: * Ignore cpuset if GFP_ATOMIC (!wait) rather than fail alloc. * See also cpuset_zone_allowed() comment in kernel/cpuset.c. */ - page = get_page_from_freelist(gfp_mask, order, zonelist, + page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, high_zoneidx, alloc_flags); if (page) goto got_pg; @@ -1536,7 +1537,7 @@ rebalance: if (!(gfp_mask & __GFP_NOMEMALLOC)) { nofail_alloc: /* go through the zonelist yet again, ignoring mins */ - page = get_page_from_freelist(gfp_mask, order, + page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, high_zoneidx, ALLOC_NO_WATERMARKS); if (page) goto got_pg; @@ -1571,7 +1572,7 @@ nofail_alloc: drain_all_pages(); if (likely(did_some_progress)) { - page = get_page_from_freelist(gfp_mask, order, + page = get_page_from_freelist(gfp_mask, nodemask, order, zonelist, high_zoneidx, alloc_flags); if (page) goto got_pg; @@ -1587,8 +1588,9 @@ nofail_alloc: * a parallel oom killing, we must fail if we're still * under heavy pressure. */ - page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, order, - zonelist, high_zoneidx, ALLOC_WMARK_HIGH|ALLOC_CPUSET); + page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, + order, zonelist, high_zoneidx, + ALLOC_WMARK_HIGH|ALLOC_CPUSET); if (page) { clear_zonelist_oom(zonelist, gfp_mask); goto got_pg; @@ -1637,6 +1639,20 @@ got_pg: return page; } +struct page * +__alloc_pages(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist) +{ + return __alloc_pages_internal(gfp_mask, order, zonelist, NULL); +} + +struct page * +__alloc_pages_nodemask(gfp_t gfp_mask, unsigned int order, + struct zonelist *zonelist, nodemask_t *nodemask) +{ + return __alloc_pages_internal(gfp_mask, order, zonelist, nodemask); +} + EXPORT_SYMBOL(__alloc_pages); /* @@ -1880,6 +1896,12 @@ void show_free_areas(void) show_swap_cache_info(); } +static void zoneref_set_zone(struct zone *zone, struct zoneref *zoneref) +{ + zoneref->zone = zone; + zoneref->zone_idx = zone_idx(zone); +} + /* * Builds allocation fallback zone lists. * -- cgit v1.2.3 From 65d66fc02ed9433b957588071b60425b12628e25 Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 28 Apr 2008 02:12:31 -0700 Subject: mempolicy: update NUMA memory policy documentation Updates Documentation/vm/numa_memory_policy.txt and Documentation/filesystems/tmpfs.txt to describe optional mempolicy mode flags. Cc: Christoph Lameter Cc: Lee Schermerhorn Cc: Andi Kleen Cc: Randy Dunlap Signed-off-by: David Rientjes Signed-off-by: Paul Jackson Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/filesystems/tmpfs.txt | 12 +++ Documentation/vm/numa_memory_policy.txt | 131 ++++++++++++++++++++++++-------- 2 files changed, 112 insertions(+), 31 deletions(-) (limited to 'Documentation') diff --git a/Documentation/filesystems/tmpfs.txt b/Documentation/filesystems/tmpfs.txt index 145e44086358..222437efd75a 100644 --- a/Documentation/filesystems/tmpfs.txt +++ b/Documentation/filesystems/tmpfs.txt @@ -92,6 +92,18 @@ NodeList format is a comma-separated list of decimal numbers and ranges, a range being two hyphen-separated decimal numbers, the smallest and largest node numbers in the range. For example, mpol=bind:0-3,5,7,9-15 +NUMA memory allocation policies have optional flags that can be used in +conjunction with their modes. These optional flags can be specified +when tmpfs is mounted by appending them to the mode before the NodeList. +See Documentation/vm/numa_memory_policy.txt for a list of all available +memory allocation policy mode flags. + + =static is equivalent to MPOL_F_STATIC_NODES + =relative is equivalent to MPOL_F_RELATIVE_NODES + +For example, mpol=bind=static:NodeList, is the equivalent of an +allocation policy of MPOL_BIND | MPOL_F_STATIC_NODES. + Note that trying to mount a tmpfs with an mpol option will fail if the running kernel does not support NUMA; and will fail if its nodelist specifies a node which is not online. If your system relies on that diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index 1278e685d650..706410dfb9e5 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt @@ -135,9 +135,11 @@ most general to most specific: Components of Memory Policies - A Linux memory policy is a tuple consisting of a "mode" and an optional set - of nodes. The mode determine the behavior of the policy, while the - optional set of nodes can be viewed as the arguments to the behavior. + A Linux memory policy consists of a "mode", optional mode flags, and an + optional set of nodes. The mode determines the behavior of the policy, + the optional mode flags determine the behavior of the mode, and the + optional set of nodes can be viewed as the arguments to the policy + behavior. Internally, memory policies are implemented by a reference counted structure, struct mempolicy. Details of this structure will be discussed @@ -179,7 +181,8 @@ Components of Memory Policies on a non-shared region of the address space. However, see MPOL_PREFERRED below. - The Default mode does not use the optional set of nodes. + It is an error for the set of nodes specified for this policy to + be non-empty. MPOL_BIND: This mode specifies that memory must come from the set of nodes specified by the policy. Memory will be allocated from @@ -226,6 +229,80 @@ Components of Memory Policies the temporary interleaved system default policy works in this mode. + Linux memory policy supports the following optional mode flags: + + MPOL_F_STATIC_NODES: This flag specifies that the nodemask passed by + the user should not be remapped if the task or VMA's set of allowed + nodes changes after the memory policy has been defined. + + Without this flag, anytime a mempolicy is rebound because of a + change in the set of allowed nodes, the node (Preferred) or + nodemask (Bind, Interleave) is remapped to the new set of + allowed nodes. This may result in nodes being used that were + previously undesired. + + With this flag, if the user-specified nodes overlap with the + nodes allowed by the task's cpuset, then the memory policy is + applied to their intersection. If the two sets of nodes do not + overlap, the Default policy is used. + + For example, consider a task that is attached to a cpuset with + mems 1-3 that sets an Interleave policy over the same set. If + the cpuset's mems change to 3-5, the Interleave will now occur + over nodes 3, 4, and 5. With this flag, however, since only node + 3 is allowed from the user's nodemask, the "interleave" only + occurs over that node. If no nodes from the user's nodemask are + now allowed, the Default behavior is used. + + MPOL_F_STATIC_NODES cannot be used with MPOL_F_RELATIVE_NODES. + + MPOL_F_RELATIVE_NODES: This flag specifies that the nodemask passed + by the user will be mapped relative to the set of the task or VMA's + set of allowed nodes. The kernel stores the user-passed nodemask, + and if the allowed nodes changes, then that original nodemask will + be remapped relative to the new set of allowed nodes. + + Without this flag (and without MPOL_F_STATIC_NODES), anytime a + mempolicy is rebound because of a change in the set of allowed + nodes, the node (Preferred) or nodemask (Bind, Interleave) is + remapped to the new set of allowed nodes. That remap may not + preserve the relative nature of the user's passed nodemask to its + set of allowed nodes upon successive rebinds: a nodemask of + 1,3,5 may be remapped to 7-9 and then to 1-3 if the set of + allowed nodes is restored to its original state. + + With this flag, the remap is done so that the node numbers from + the user's passed nodemask are relative to the set of allowed + nodes. In other words, if nodes 0, 2, and 4 are set in the user's + nodemask, the policy will be effected over the first (and in the + Bind or Interleave case, the third and fifth) nodes in the set of + allowed nodes. The nodemask passed by the user represents nodes + relative to task or VMA's set of allowed nodes. + + If the user's nodemask includes nodes that are outside the range + of the new set of allowed nodes (for example, node 5 is set in + the user's nodemask when the set of allowed nodes is only 0-3), + then the remap wraps around to the beginning of the nodemask and, + if not already set, sets the node in the mempolicy nodemask. + + For example, consider a task that is attached to a cpuset with + mems 2-5 that sets an Interleave policy over the same set with + MPOL_F_RELATIVE_NODES. If the cpuset's mems change to 3-7, the + interleave now occurs over nodes 3,5-6. If the cpuset's mems + then change to 0,2-3,5, then the interleave occurs over nodes + 0,3,5. + + Thanks to the consistent remapping, applications preparing + nodemasks to specify memory policies using this flag should + disregard their current, actual cpuset imposed memory placement + and prepare the nodemask as if they were always located on + memory nodes 0 to N-1, where N is the number of memory nodes the + policy is intended to manage. Let the kernel then remap to the + set of memory nodes allowed by the task's cpuset, as that may + change over time. + + MPOL_F_RELATIVE_NODES cannot be used with MPOL_F_STATIC_NODES. + MEMORY POLICY APIs Linux supports 3 system calls for controlling memory policy. These APIS @@ -246,7 +323,9 @@ Set [Task] Memory Policy: Set's the calling task's "task/process memory policy" to mode specified by the 'mode' argument and the set of nodes defined by 'nmask'. 'nmask' points to a bit mask of node ids containing - at least 'maxnode' ids. + at least 'maxnode' ids. Optional mode flags may be passed by + combining the 'mode' argument with the flag (for example: + MPOL_INTERLEAVE | MPOL_F_STATIC_NODES). See the set_mempolicy(2) man page for more details @@ -298,29 +377,19 @@ MEMORY POLICIES AND CPUSETS Memory policies work within cpusets as described above. For memory policies that require a node or set of nodes, the nodes are restricted to the set of nodes whose memories are allowed by the cpuset constraints. If the nodemask -specified for the policy contains nodes that are not allowed by the cpuset, or -the intersection of the set of nodes specified for the policy and the set of -nodes with memory is the empty set, the policy is considered invalid -and cannot be installed. - -The interaction of memory policies and cpusets can be problematic for a -couple of reasons: - -1) the memory policy APIs take physical node id's as arguments. As mentioned - above, it is illegal to specify nodes that are not allowed in the cpuset. - The application must query the allowed nodes using the get_mempolicy() - API with the MPOL_F_MEMS_ALLOWED flag to determine the allowed nodes and - restrict itself to those nodes. However, the resources available to a - cpuset can be changed by the system administrator, or a workload manager - application, at any time. So, a task may still get errors attempting to - specify policy nodes, and must query the allowed memories again. - -2) when tasks in two cpusets share access to a memory region, such as shared - memory segments created by shmget() of mmap() with the MAP_ANONYMOUS and - MAP_SHARED flags, and any of the tasks install shared policy on the region, - only nodes whose memories are allowed in both cpusets may be used in the - policies. Obtaining this information requires "stepping outside" the - memory policy APIs to use the cpuset information and requires that one - know in what cpusets other task might be attaching to the shared region. - Furthermore, if the cpusets' allowed memory sets are disjoint, "local" - allocation is the only valid policy. +specified for the policy contains nodes that are not allowed by the cpuset and +MPOL_F_RELATIVE_NODES is not used, the intersection of the set of nodes +specified for the policy and the set of nodes with memory is used. If the +result is the empty set, the policy is considered invalid and cannot be +installed. If MPOL_F_RELATIVE_NODES is used, the policy's nodes are mapped +onto and folded into the task's set of allowed nodes as previously described. + +The interaction of memory policies and cpusets can be problematic when tasks +in two cpusets share access to a memory region, such as shared memory segments +created by shmget() of mmap() with the MAP_ANONYMOUS and MAP_SHARED flags, and +any of the tasks install shared policy on the region, only nodes whose +memories are allowed in both cpusets may be used in the policies. Obtaining +this information requires "stepping outside" the memory policy APIs to use the +cpuset information and requires that one know in what cpusets other task might +be attaching to the shared region. Furthermore, if the cpusets' allowed +memory sets are disjoint, "local" allocation is the only valid policy. -- cgit v1.2.3 From 3e1f064562fcff7bf3856bc1d00dfa84d4f121cc Mon Sep 17 00:00:00 2001 From: David Rientjes Date: Mon, 28 Apr 2008 02:12:34 -0700 Subject: mempolicy: disallow static or relative flags for local preferred mode MPOL_F_STATIC_NODES and MPOL_F_RELATIVE_NODES don't mean anything for MPOL_PREFERRED policies that were created with an empty nodemask (for purely local allocations). They'll never be invalidated because the allowed mems of a task changes or need to be rebound relative to a cpuset's placement. Also fixes a bug identified by Lee Schermerhorn that disallowed empty nodemasks to be passed to MPOL_PREFERRED to specify local allocations. [A different, somewhat incomplete, patch already existed in 25-rc5-mm1.] Cc: Paul Jackson Cc: Christoph Lameter Cc: Lee Schermerhorn Cc: Andi Kleen Cc: Randy Dunlap Signed-off-by: Lee Schermerhorn Signed-off-by: David Rientjes Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/numa_memory_policy.txt | 16 +++++++++++-- mm/mempolicy.c | 42 ++++++++++++++++++++------------- 2 files changed, 40 insertions(+), 18 deletions(-) (limited to 'Documentation') diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index 706410dfb9e5..1c7dd21623d2 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt @@ -205,6 +205,12 @@ Components of Memory Policies local allocation for a specific range of addresses--i.e. for VMA policies. + It is possible for the user to specify that local allocation is + always preferred by passing an empty nodemask with this mode. + If an empty nodemask is passed, the policy cannot use the + MPOL_F_STATIC_NODES or MPOL_F_RELATIVE_NODES flags described + below. + MPOL_INTERLEAVED: This mode specifies that page allocations be interleaved, on a page granularity, across the nodes specified in the policy. This mode also behaves slightly differently, based on @@ -254,7 +260,10 @@ Components of Memory Policies occurs over that node. If no nodes from the user's nodemask are now allowed, the Default behavior is used. - MPOL_F_STATIC_NODES cannot be used with MPOL_F_RELATIVE_NODES. + MPOL_F_STATIC_NODES cannot be combined with the + MPOL_F_RELATIVE_NODES flag. It also cannot be used for + MPOL_PREFERRED policies that were created with an empty nodemask + (local allocation). MPOL_F_RELATIVE_NODES: This flag specifies that the nodemask passed by the user will be mapped relative to the set of the task or VMA's @@ -301,7 +310,10 @@ Components of Memory Policies set of memory nodes allowed by the task's cpuset, as that may change over time. - MPOL_F_RELATIVE_NODES cannot be used with MPOL_F_STATIC_NODES. + MPOL_F_RELATIVE_NODES cannot be combined with the + MPOL_F_STATIC_NODES flag. It also cannot be used for + MPOL_PREFERRED policies that were created with an empty nodemask + (local allocation). MEMORY POLICY APIs diff --git a/mm/mempolicy.c b/mm/mempolicy.c index a94d994eaaa8..c1b907789d84 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -181,27 +181,43 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags, { struct mempolicy *policy; nodemask_t cpuset_context_nmask; - int localalloc = 0; int ret; pr_debug("setting mode %d flags %d nodes[0] %lx\n", mode, flags, nodes ? nodes_addr(*nodes)[0] : -1); - if (mode == MPOL_DEFAULT) - return NULL; - if (!nodes || nodes_empty(*nodes)) { - if (mode != MPOL_PREFERRED) + if (mode == MPOL_DEFAULT) { + if (nodes && !nodes_empty(*nodes)) return ERR_PTR(-EINVAL); - localalloc = 1; /* special case: no mode flags */ + return NULL; } + VM_BUG_ON(!nodes); + + /* + * MPOL_PREFERRED cannot be used with MPOL_F_STATIC_NODES or + * MPOL_F_RELATIVE_NODES if the nodemask is empty (local allocation). + * All other modes require a valid pointer to a non-empty nodemask. + */ + if (mode == MPOL_PREFERRED) { + if (nodes_empty(*nodes)) { + if (((flags & MPOL_F_STATIC_NODES) || + (flags & MPOL_F_RELATIVE_NODES))) + return ERR_PTR(-EINVAL); + nodes = NULL; /* flag local alloc */ + } + } else if (nodes_empty(*nodes)) + return ERR_PTR(-EINVAL); policy = kmem_cache_alloc(policy_cache, GFP_KERNEL); if (!policy) return ERR_PTR(-ENOMEM); atomic_set(&policy->refcnt, 1); policy->policy = mode; + policy->flags = flags; - if (!localalloc) { - policy->flags = flags; + if (nodes) { + /* + * cpuset related setup doesn't apply to local allocation + */ cpuset_update_task_memory_state(); if (flags & MPOL_F_RELATIVE_NODES) mpol_relative_nodemask(&cpuset_context_nmask, nodes, @@ -217,7 +233,7 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags, } ret = mpol_ops[mode].create(policy, - localalloc ? NULL : &cpuset_context_nmask); + nodes ? &cpuset_context_nmask : NULL); if (ret < 0) { kmem_cache_free(policy_cache, policy); return ERR_PTR(ret); @@ -259,10 +275,6 @@ static void mpol_rebind_preferred(struct mempolicy *pol, { nodemask_t tmp; - /* - * check 'STATIC_NODES first, as preferred_node == -1 may be - * a temporary, "fallback" state for this policy. - */ if (pol->flags & MPOL_F_STATIC_NODES) { int node = first_node(pol->w.user_nodemask); @@ -270,12 +282,10 @@ static void mpol_rebind_preferred(struct mempolicy *pol, pol->v.preferred_node = node; else pol->v.preferred_node = -1; - } else if (pol->v.preferred_node == -1) { - return; /* no remap required for explicit local alloc */ } else if (pol->flags & MPOL_F_RELATIVE_NODES) { mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, nodes); pol->v.preferred_node = first_node(tmp); - } else { + } else if (pol->v.preferred_node != -1) { pol->v.preferred_node = node_remap(pol->v.preferred_node, pol->w.cpuset_mems_allowed, *nodes); -- cgit v1.2.3 From 45c4745af381851b0406d8e4db99e62e265691c2 Mon Sep 17 00:00:00 2001 From: Lee Schermerhorn Date: Mon, 28 Apr 2008 02:13:12 -0700 Subject: mempolicy: rename struct mempolicy 'policy' member to 'mode' The terms 'policy' and 'mode' are both used in various places to describe the semantics of the value stored in the 'policy' member of struct mempolicy. Furthermore, the term 'policy' is used to refer to that member, to the entire struct mempolicy and to the more abstract concept of the tuple consisting of a "mode" and an optional node or set of nodes. Recently, we have added "mode flags" that are passed in the upper bits of the 'mode' [or sometimes, 'policy'] member of the numa APIs. I'd like to resolve this confusion, which perhaps only exists in my mind, by renaming the 'policy' member to 'mode' throughout, and fixing up the Documentation. Man pages will be updated separately. Signed-off-by: Lee Schermerhorn Cc: Christoph Lameter Cc: David Rientjes Cc: Mel Gorman Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/numa_memory_policy.txt | 4 --- include/linux/mempolicy.h | 6 ++--- mm/mempolicy.c | 46 ++++++++++++++++----------------- 3 files changed, 26 insertions(+), 30 deletions(-) (limited to 'Documentation') diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index 1c7dd21623d2..27b9507a3769 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt @@ -145,10 +145,6 @@ Components of Memory Policies structure, struct mempolicy. Details of this structure will be discussed in context, below, as required to explain the behavior. - Note: in some functions AND in the struct mempolicy itself, the mode - is called "policy". However, to avoid confusion with the policy tuple, - this document will continue to use the term "mode". - Linux memory policy supports the following 4 behavioral modes: Default Mode--MPOL_DEFAULT: The behavior specified by this mode is diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 5e19c2275a6f..9080fab1426d 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -80,7 +80,7 @@ struct mm_struct; */ struct mempolicy { atomic_t refcnt; - unsigned short policy; /* See MPOL_* above */ + unsigned short mode; /* See MPOL_* above */ unsigned short flags; /* See set_mempolicy() MPOL_F_* above */ union { short preferred_node; /* preferred */ @@ -149,7 +149,7 @@ struct shared_policy { spinlock_t lock; }; -void mpol_shared_policy_init(struct shared_policy *info, unsigned short policy, +void mpol_shared_policy_init(struct shared_policy *info, unsigned short mode, unsigned short flags, nodemask_t *nodes); int mpol_set_shared_policy(struct shared_policy *info, struct vm_area_struct *vma, @@ -213,7 +213,7 @@ static inline int mpol_set_shared_policy(struct shared_policy *info, } static inline void mpol_shared_policy_init(struct shared_policy *info, - unsigned short policy, unsigned short flags, nodemask_t *nodes) + unsigned short mode, unsigned short flags, nodemask_t *nodes) { } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 8924aaf4665c..5e7eea2dc8b4 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -106,7 +106,7 @@ enum zone_type policy_zone = 0; struct mempolicy default_policy = { .refcnt = ATOMIC_INIT(1), /* never free it */ - .policy = MPOL_DEFAULT, + .mode = MPOL_DEFAULT, }; static const struct mempolicy_operations { @@ -211,7 +211,7 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags, if (!policy) return ERR_PTR(-ENOMEM); atomic_set(&policy->refcnt, 1); - policy->policy = mode; + policy->mode = mode; policy->flags = flags; if (nodes) { @@ -302,7 +302,7 @@ static void mpol_rebind_policy(struct mempolicy *pol, if (!mpol_store_user_nodemask(pol) && nodes_equal(pol->w.cpuset_mems_allowed, *newmask)) return; - mpol_ops[pol->policy].rebind(pol, newmask); + mpol_ops[pol->mode].rebind(pol, newmask); } /* @@ -608,7 +608,7 @@ static long do_set_mempolicy(unsigned short mode, unsigned short flags, mpol_put(current->mempolicy); current->mempolicy = new; mpol_set_task_struct_flag(); - if (new && new->policy == MPOL_INTERLEAVE && + if (new && new->mode == MPOL_INTERLEAVE && nodes_weight(new->v.nodes)) current->il_next = first_node(new->v.nodes); if (mm) @@ -621,7 +621,7 @@ static long do_set_mempolicy(unsigned short mode, unsigned short flags, static void get_zonemask(struct mempolicy *p, nodemask_t *nodes) { nodes_clear(*nodes); - switch (p->policy) { + switch (p->mode) { case MPOL_DEFAULT: break; case MPOL_BIND: @@ -700,14 +700,14 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, goto out; *policy = err; } else if (pol == current->mempolicy && - pol->policy == MPOL_INTERLEAVE) { + pol->mode == MPOL_INTERLEAVE) { *policy = current->il_next; } else { err = -EINVAL; goto out; } } else - *policy = pol->policy | pol->flags; + *policy = pol->mode | pol->flags; if (vma) { up_read(¤t->mm->mmap_sem); @@ -1276,7 +1276,7 @@ static struct mempolicy *get_vma_policy(struct task_struct *task, pol = vpol; shared_pol = 1; /* if pol non-NULL, add ref below */ } else if (vma->vm_policy && - vma->vm_policy->policy != MPOL_DEFAULT) + vma->vm_policy->mode != MPOL_DEFAULT) pol = vma->vm_policy; } if (!pol) @@ -1290,7 +1290,7 @@ static struct mempolicy *get_vma_policy(struct task_struct *task, static nodemask_t *nodemask_policy(gfp_t gfp, struct mempolicy *policy) { /* Lower zones don't get a nodemask applied for MPOL_BIND */ - if (unlikely(policy->policy == MPOL_BIND) && + if (unlikely(policy->mode == MPOL_BIND) && gfp_zone(gfp) >= policy_zone && cpuset_nodemask_valid_mems_allowed(&policy->v.nodes)) return &policy->v.nodes; @@ -1303,7 +1303,7 @@ static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy) { int nd; - switch (policy->policy) { + switch (policy->mode) { case MPOL_PREFERRED: nd = policy->v.preferred_node; if (nd < 0) @@ -1353,7 +1353,7 @@ static unsigned interleave_nodes(struct mempolicy *policy) */ unsigned slab_node(struct mempolicy *policy) { - unsigned short pol = policy ? policy->policy : MPOL_DEFAULT; + unsigned short pol = policy ? policy->mode : MPOL_DEFAULT; switch (pol) { case MPOL_INTERLEAVE: @@ -1454,9 +1454,9 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, *mpol = NULL; /* probably no unref needed */ *nodemask = NULL; /* assume !MPOL_BIND */ - if (pol->policy == MPOL_BIND) { + if (pol->mode == MPOL_BIND) { *nodemask = &pol->v.nodes; - } else if (pol->policy == MPOL_INTERLEAVE) { + } else if (pol->mode == MPOL_INTERLEAVE) { unsigned nid; nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); @@ -1468,7 +1468,7 @@ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, zl = zonelist_policy(GFP_HIGHUSER, pol); if (unlikely(pol != &default_policy && pol != current->mempolicy)) { - if (pol->policy != MPOL_BIND) + if (pol->mode != MPOL_BIND) __mpol_put(pol); /* finished with pol */ else *mpol = pol; /* unref needed after allocation */ @@ -1522,7 +1522,7 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) cpuset_update_task_memory_state(); - if (unlikely(pol->policy == MPOL_INTERLEAVE)) { + if (unlikely(pol->mode == MPOL_INTERLEAVE)) { unsigned nid; nid = interleave_nid(pol, vma, addr, PAGE_SHIFT); @@ -1574,7 +1574,7 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order) cpuset_update_task_memory_state(); if (!pol || in_interrupt() || (gfp & __GFP_THISNODE)) pol = &default_policy; - if (pol->policy == MPOL_INTERLEAVE) + if (pol->mode == MPOL_INTERLEAVE) return alloc_page_interleave(gfp, order, interleave_nodes(pol)); return __alloc_pages_nodemask(gfp, order, zonelist_policy(gfp, pol), nodemask_policy(gfp, pol)); @@ -1620,11 +1620,11 @@ int __mpol_equal(struct mempolicy *a, struct mempolicy *b) { if (!a || !b) return 0; - if (a->policy != b->policy) + if (a->mode != b->mode) return 0; - if (a->policy != MPOL_DEFAULT && !mpol_match_intent(a, b)) + if (a->mode != MPOL_DEFAULT && !mpol_match_intent(a, b)) return 0; - switch (a->policy) { + switch (a->mode) { case MPOL_DEFAULT: return 1; case MPOL_BIND: @@ -1644,7 +1644,7 @@ void __mpol_put(struct mempolicy *p) { if (!atomic_dec_and_test(&p->refcnt)) return; - p->policy = MPOL_DEFAULT; + p->mode = MPOL_DEFAULT; kmem_cache_free(policy_cache, p); } @@ -1710,7 +1710,7 @@ static void sp_insert(struct shared_policy *sp, struct sp_node *new) rb_link_node(&new->nd, parent, p); rb_insert_color(&new->nd, &sp->root); pr_debug("inserting %lx-%lx: %d\n", new->start, new->end, - new->policy ? new->policy->policy : 0); + new->policy ? new->policy->mode : 0); } /* Find shared policy intersecting idx */ @@ -1835,7 +1835,7 @@ int mpol_set_shared_policy(struct shared_policy *info, pr_debug("set_shared_policy %lx sz %lu %d %d %lx\n", vma->vm_pgoff, - sz, npol ? npol->policy : -1, + sz, npol ? npol->mode : -1, npol ? npol->flags : -1, npol ? nodes_addr(npol->v.nodes)[0] : -1); @@ -1935,7 +1935,7 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) char *p = buffer; int l; nodemask_t nodes; - unsigned short mode = pol ? pol->policy : MPOL_DEFAULT; + unsigned short mode = pol ? pol->mode : MPOL_DEFAULT; unsigned short flags = pol ? pol->flags : 0; switch (mode) { -- cgit v1.2.3 From 52cd3b074050dd664380b5e8cfc85d4a6ed8ad48 Mon Sep 17 00:00:00 2001 From: Lee Schermerhorn Date: Mon, 28 Apr 2008 02:13:16 -0700 Subject: mempolicy: rework mempolicy Reference Counting [yet again] After further discussion with Christoph Lameter, it has become clear that my earlier attempts to clean up the mempolicy reference counting were a bit of overkill in some areas, resulting in superflous ref/unref in what are usually fast paths. In other areas, further inspection reveals that I botched the unref for interleave policies. A separate patch, suitable for upstream/stable trees, fixes up the known errors in the previous attempt to fix reference counting. This patch reworks the memory policy referencing counting and, one hopes, simplifies the code. Maybe I'll get it right this time. See the update to the numa_memory_policy.txt document for a discussion of memory policy reference counting that motivates this patch. Summary: Lookup of mempolicy, based on (vma, address) need only add a reference for shared policy, and we need only unref the policy when finished for shared policies. So, this patch backs out all of the unneeded extra reference counting added by my previous attempt. It then unrefs only shared policies when we're finished with them, using the mpol_cond_put() [conditional put] helper function introduced by this patch. Note that shmem_swapin() calls read_swap_cache_async() with a dummy vma containing just the policy. read_swap_cache_async() can call alloc_page_vma() multiple times, so we can't let alloc_page_vma() unref the shared policy in this case. To avoid this, we make a copy of any non-null shared policy and remove the MPOL_F_SHARED flag from the copy. This copy occurs before reading a page [or multiple pages] from swap, so the overhead should not be an issue here. I introduced a new static inline function "mpol_cond_copy()" to copy the shared policy to an on-stack policy and remove the flags that would require a conditional free. The current implementation of mpol_cond_copy() assumes that the struct mempolicy contains no pointers to dynamically allocated structures that must be duplicated or reference counted during copy. Signed-off-by: Lee Schermerhorn Cc: Christoph Lameter Cc: David Rientjes Cc: Mel Gorman Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/numa_memory_policy.txt | 68 +++++++++++++++ include/linux/mempolicy.h | 35 ++++++++ ipc/shm.c | 5 +- mm/hugetlb.c | 2 +- mm/mempolicy.c | 146 +++++++++++++++++--------------- mm/shmem.c | 16 ++-- 6 files changed, 195 insertions(+), 77 deletions(-) (limited to 'Documentation') diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index 27b9507a3769..6719d642653f 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt @@ -311,6 +311,74 @@ Components of Memory Policies MPOL_PREFERRED policies that were created with an empty nodemask (local allocation). +MEMORY POLICY REFERENCE COUNTING + +To resolve use/free races, struct mempolicy contains an atomic reference +count field. Internal interfaces, mpol_get()/mpol_put() increment and +decrement this reference count, respectively. mpol_put() will only free +the structure back to the mempolicy kmem cache when the reference count +goes to zero. + +When a new memory policy is allocated, it's reference count is initialized +to '1', representing the reference held by the task that is installing the +new policy. When a pointer to a memory policy structure is stored in another +structure, another reference is added, as the task's reference will be dropped +on completion of the policy installation. + +During run-time "usage" of the policy, we attempt to minimize atomic operations +on the reference count, as this can lead to cache lines bouncing between cpus +and NUMA nodes. "Usage" here means one of the following: + +1) querying of the policy, either by the task itself [using the get_mempolicy() + API discussed below] or by another task using the /proc//numa_maps + interface. + +2) examination of the policy to determine the policy mode and associated node + or node lists, if any, for page allocation. This is considered a "hot + path". Note that for MPOL_BIND, the "usage" extends across the entire + allocation process, which may sleep during page reclaimation, because the + BIND policy nodemask is used, by reference, to filter ineligible nodes. + +We can avoid taking an extra reference during the usages listed above as +follows: + +1) we never need to get/free the system default policy as this is never + changed nor freed, once the system is up and running. + +2) for querying the policy, we do not need to take an extra reference on the + target task's task policy nor vma policies because we always acquire the + task's mm's mmap_sem for read during the query. The set_mempolicy() and + mbind() APIs [see below] always acquire the mmap_sem for write when + installing or replacing task or vma policies. Thus, there is no possibility + of a task or thread freeing a policy while another task or thread is + querying it. + +3) Page allocation usage of task or vma policy occurs in the fault path where + we hold them mmap_sem for read. Again, because replacing the task or vma + policy requires that the mmap_sem be held for write, the policy can't be + freed out from under us while we're using it for page allocation. + +4) Shared policies require special consideration. One task can replace a + shared memory policy while another task, with a distinct mmap_sem, is + querying or allocating a page based on the policy. To resolve this + potential race, the shared policy infrastructure adds an extra reference + to the shared policy during lookup while holding a spin lock on the shared + policy management structure. This requires that we drop this extra + reference when we're finished "using" the policy. We must drop the + extra reference on shared policies in the same query/allocation paths + used for non-shared policies. For this reason, shared policies are marked + as such, and the extra reference is dropped "conditionally"--i.e., only + for shared policies. + + Because of this extra reference counting, and because we must lookup + shared policies in a tree structure under spinlock, shared policies are + more expensive to use in the page allocation path. This is expecially + true for shared policies on shared memory regions shared by tasks running + on different NUMA nodes. This extra overhead can be avoided by always + falling back to task or system default policy for shared memory regions, + or by prefaulting the entire shared memory region into memory and locking + it down. However, this might not be appropriate for all applications. + MEMORY POLICY APIs Linux supports 3 system calls for controlling memory policy. These APIS diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 017def89e568..172b9c6acb91 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -112,6 +112,31 @@ static inline void mpol_put(struct mempolicy *pol) __mpol_put(pol); } +/* + * Does mempolicy pol need explicit unref after use? + * Currently only needed for shared policies. + */ +static inline int mpol_needs_cond_ref(struct mempolicy *pol) +{ + return (pol && (pol->flags & MPOL_F_SHARED)); +} + +static inline void mpol_cond_put(struct mempolicy *pol) +{ + if (mpol_needs_cond_ref(pol)) + __mpol_put(pol); +} + +extern struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol, + struct mempolicy *frompol); +static inline struct mempolicy *mpol_cond_copy(struct mempolicy *tompol, + struct mempolicy *frompol) +{ + if (!frompol) + return frompol; + return __mpol_cond_copy(tompol, frompol); +} + extern struct mempolicy *__mpol_dup(struct mempolicy *pol); static inline struct mempolicy *mpol_dup(struct mempolicy *pol) { @@ -201,6 +226,16 @@ static inline void mpol_put(struct mempolicy *p) { } +static inline void mpol_cond_put(struct mempolicy *pol) +{ +} + +static inline struct mempolicy *mpol_cond_copy(struct mempolicy *to, + struct mempolicy *from) +{ + return from; +} + static inline void mpol_get(struct mempolicy *pol) { } diff --git a/ipc/shm.c b/ipc/shm.c index 8d1b2c468cc4..e636910454a9 100644 --- a/ipc/shm.c +++ b/ipc/shm.c @@ -271,10 +271,9 @@ static struct mempolicy *shm_get_policy(struct vm_area_struct *vma, if (sfd->vm_ops->get_policy) pol = sfd->vm_ops->get_policy(vma, addr); - else if (vma->vm_policy) { + else if (vma->vm_policy) pol = vma->vm_policy; - mpol_get(pol); /* get_vma_policy() expects this */ - } + return pol; } #endif diff --git a/mm/hugetlb.c b/mm/hugetlb.c index 53afa8c76ada..d36e1f11a5f2 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -116,7 +116,7 @@ static struct page *dequeue_huge_page_vma(struct vm_area_struct *vma, break; } } - mpol_put(mpol); /* unref if mpol !NULL */ + mpol_cond_put(mpol); return page; } diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 78b18a60b9b2..a237295f8190 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -241,6 +241,15 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags, return policy; } +/* Slow path of a mpol destructor. */ +void __mpol_put(struct mempolicy *p) +{ + if (!atomic_dec_and_test(&p->refcnt)) + return; + p->mode = MPOL_DEFAULT; + kmem_cache_free(policy_cache, p); +} + static void mpol_rebind_default(struct mempolicy *pol, const nodemask_t *nodes) { } @@ -719,6 +728,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, get_zonemask(pol, nmask); out: + mpol_cond_put(pol); if (vma) up_read(¤t->mm->mmap_sem); return err; @@ -1257,16 +1267,18 @@ asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len, * * Returns effective policy for a VMA at specified address. * Falls back to @task or system default policy, as necessary. - * Returned policy has extra reference count if shared, vma, - * or some other task's policy [show_numa_maps() can pass - * @task != current]. It is the caller's responsibility to - * free the reference in these cases. + * Current or other task's task mempolicy and non-shared vma policies + * are protected by the task's mmap_sem, which must be held for read by + * the caller. + * Shared policies [those marked as MPOL_F_SHARED] require an extra reference + * count--added by the get_policy() vm_op, as appropriate--to protect against + * freeing by another task. It is the caller's responsibility to free the + * extra reference for shared policies. */ static struct mempolicy *get_vma_policy(struct task_struct *task, struct vm_area_struct *vma, unsigned long addr) { struct mempolicy *pol = task->mempolicy; - int shared_pol = 0; if (vma) { if (vma->vm_ops && vma->vm_ops->get_policy) { @@ -1274,20 +1286,20 @@ static struct mempolicy *get_vma_policy(struct task_struct *task, addr); if (vpol) pol = vpol; - shared_pol = 1; /* if pol non-NULL, add ref below */ } else if (vma->vm_policy && vma->vm_policy->mode != MPOL_DEFAULT) pol = vma->vm_policy; } if (!pol) pol = &default_policy; - else if (!shared_pol && pol != current->mempolicy) - mpol_get(pol); /* vma or other task's policy */ return pol; } -/* Return a nodemask representing a mempolicy */ -static nodemask_t *nodemask_policy(gfp_t gfp, struct mempolicy *policy) +/* + * Return a nodemask representing a mempolicy for filtering nodes for + * page allocation + */ +static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy) { /* Lower zones don't get a nodemask applied for MPOL_BIND */ if (unlikely(policy->mode == MPOL_BIND) && @@ -1298,8 +1310,8 @@ static nodemask_t *nodemask_policy(gfp_t gfp, struct mempolicy *policy) return NULL; } -/* Return a zonelist representing a mempolicy */ -static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy) +/* Return a zonelist indicated by gfp for node representing a mempolicy */ +static struct zonelist *policy_zonelist(gfp_t gfp, struct mempolicy *policy) { int nd; @@ -1311,10 +1323,10 @@ static struct zonelist *zonelist_policy(gfp_t gfp, struct mempolicy *policy) break; case MPOL_BIND: /* - * Normally, MPOL_BIND allocations node-local are node-local - * within the allowed nodemask. However, if __GFP_THISNODE is - * set and the current node is part of the mask, we use the - * the zonelist for the first node in the mask instead. + * Normally, MPOL_BIND allocations are node-local within the + * allowed nodemask. However, if __GFP_THISNODE is set and the + * current node is part of the mask, we use the zonelist for + * the first node in the mask instead. */ nd = numa_node_id(); if (unlikely(gfp & __GFP_THISNODE) && @@ -1350,6 +1362,10 @@ static unsigned interleave_nodes(struct mempolicy *policy) /* * Depending on the memory policy provide a node from which to allocate the * next slab entry. + * @policy must be protected by freeing by the caller. If @policy is + * the current task's mempolicy, this protection is implicit, as only the + * task can change it's policy. The system default policy requires no + * such protection. */ unsigned slab_node(struct mempolicy *policy) { @@ -1435,43 +1451,27 @@ static inline unsigned interleave_nid(struct mempolicy *pol, * @mpol = pointer to mempolicy pointer for reference counted mempolicy * @nodemask = pointer to nodemask pointer for MPOL_BIND nodemask * - * Returns a zonelist suitable for a huge page allocation. - * If the effective policy is 'BIND, returns pointer to local node's zonelist, - * and a pointer to the mempolicy's @nodemask for filtering the zonelist. - * If it is also a policy for which get_vma_policy() returns an extra - * reference, we must hold that reference until after the allocation. - * In that case, return policy via @mpol so hugetlb allocation can drop - * the reference. For non-'BIND referenced policies, we can/do drop the - * reference here, so the caller doesn't need to know about the special case - * for default and current task policy. + * Returns a zonelist suitable for a huge page allocation and a pointer + * to the struct mempolicy for conditional unref after allocation. + * If the effective policy is 'BIND, returns a pointer to the mempolicy's + * @nodemask for filtering the zonelist. */ struct zonelist *huge_zonelist(struct vm_area_struct *vma, unsigned long addr, gfp_t gfp_flags, struct mempolicy **mpol, nodemask_t **nodemask) { - struct mempolicy *pol = get_vma_policy(current, vma, addr); struct zonelist *zl; - *mpol = NULL; /* probably no unref needed */ + *mpol = get_vma_policy(current, vma, addr); *nodemask = NULL; /* assume !MPOL_BIND */ - if (pol->mode == MPOL_BIND) { - *nodemask = &pol->v.nodes; - } else if (pol->mode == MPOL_INTERLEAVE) { - unsigned nid; - - nid = interleave_nid(pol, vma, addr, HPAGE_SHIFT); - if (unlikely(pol != &default_policy && - pol != current->mempolicy)) - __mpol_put(pol); /* finished with pol */ - return node_zonelist(nid, gfp_flags); - } - zl = zonelist_policy(GFP_HIGHUSER, pol); - if (unlikely(pol != &default_policy && pol != current->mempolicy)) { - if (pol->mode != MPOL_BIND) - __mpol_put(pol); /* finished with pol */ - else - *mpol = pol; /* unref needed after allocation */ + if (unlikely((*mpol)->mode == MPOL_INTERLEAVE)) { + zl = node_zonelist(interleave_nid(*mpol, vma, addr, + HPAGE_SHIFT), gfp_flags); + } else { + zl = policy_zonelist(gfp_flags, *mpol); + if ((*mpol)->mode == MPOL_BIND) + *nodemask = &(*mpol)->v.nodes; } return zl; } @@ -1526,25 +1526,23 @@ alloc_page_vma(gfp_t gfp, struct vm_area_struct *vma, unsigned long addr) unsigned nid; nid = interleave_nid(pol, vma, addr, PAGE_SHIFT); - if (unlikely(pol != &default_policy && - pol != current->mempolicy)) - __mpol_put(pol); /* finished with pol */ + mpol_cond_put(pol); return alloc_page_interleave(gfp, 0, nid); } - zl = zonelist_policy(gfp, pol); - if (pol != &default_policy && pol != current->mempolicy) { + zl = policy_zonelist(gfp, pol); + if (unlikely(mpol_needs_cond_ref(pol))) { /* - * slow path: ref counted policy -- shared or vma + * slow path: ref counted shared policy */ struct page *page = __alloc_pages_nodemask(gfp, 0, - zl, nodemask_policy(gfp, pol)); + zl, policy_nodemask(gfp, pol)); __mpol_put(pol); return page; } /* * fast path: default or task policy */ - return __alloc_pages_nodemask(gfp, 0, zl, nodemask_policy(gfp, pol)); + return __alloc_pages_nodemask(gfp, 0, zl, policy_nodemask(gfp, pol)); } /** @@ -1574,10 +1572,15 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order) cpuset_update_task_memory_state(); if (!pol || in_interrupt() || (gfp & __GFP_THISNODE)) pol = &default_policy; + + /* + * No reference counting needed for current->mempolicy + * nor system default_policy + */ if (pol->mode == MPOL_INTERLEAVE) return alloc_page_interleave(gfp, order, interleave_nodes(pol)); return __alloc_pages_nodemask(gfp, order, - zonelist_policy(gfp, pol), nodemask_policy(gfp, pol)); + policy_zonelist(gfp, pol), policy_nodemask(gfp, pol)); } EXPORT_SYMBOL(alloc_pages_current); @@ -1605,6 +1608,28 @@ struct mempolicy *__mpol_dup(struct mempolicy *old) return new; } +/* + * If *frompol needs [has] an extra ref, copy *frompol to *tompol , + * eliminate the * MPOL_F_* flags that require conditional ref and + * [NOTE!!!] drop the extra ref. Not safe to reference *frompol directly + * after return. Use the returned value. + * + * Allows use of a mempolicy for, e.g., multiple allocations with a single + * policy lookup, even if the policy needs/has extra ref on lookup. + * shmem_readahead needs this. + */ +struct mempolicy *__mpol_cond_copy(struct mempolicy *tompol, + struct mempolicy *frompol) +{ + if (!mpol_needs_cond_ref(frompol)) + return frompol; + + *tompol = *frompol; + tompol->flags &= ~MPOL_F_SHARED; /* copy doesn't need unref */ + __mpol_put(frompol); + return tompol; +} + static int mpol_match_intent(const struct mempolicy *a, const struct mempolicy *b) { @@ -1639,15 +1664,6 @@ int __mpol_equal(struct mempolicy *a, struct mempolicy *b) } } -/* Slow path of a mpol destructor. */ -void __mpol_put(struct mempolicy *p) -{ - if (!atomic_dec_and_test(&p->refcnt)) - return; - p->mode = MPOL_DEFAULT; - kmem_cache_free(policy_cache, p); -} - /* * Shared memory backing store policy support. * @@ -2081,11 +2097,7 @@ int show_numa_map(struct seq_file *m, void *v) pol = get_vma_policy(priv->task, vma, vma->vm_start); mpol_to_str(buffer, sizeof(buffer), pol); - /* - * unref shared or other task's mempolicy - */ - if (pol != &default_policy && pol != current->mempolicy) - __mpol_put(pol); + mpol_cond_put(pol); seq_printf(m, "%08lx %s", vma->vm_start, buffer); diff --git a/mm/shmem.c b/mm/shmem.c index 5326876d814d..0b591c669b2d 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -1187,16 +1187,19 @@ static void shmem_show_mpol(struct seq_file *seq, unsigned short policy, static struct page *shmem_swapin(swp_entry_t entry, gfp_t gfp, struct shmem_inode_info *info, unsigned long idx) { + struct mempolicy mpol, *spol; struct vm_area_struct pvma; struct page *page; + spol = mpol_cond_copy(&mpol, + mpol_shared_policy_lookup(&info->policy, idx)); + /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; pvma.vm_pgoff = idx; pvma.vm_ops = NULL; - pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx); + pvma.vm_policy = spol; page = swapin_readahead(entry, gfp, &pvma, 0); - mpol_put(pvma.vm_policy); return page; } @@ -1204,16 +1207,17 @@ static struct page *shmem_alloc_page(gfp_t gfp, struct shmem_inode_info *info, unsigned long idx) { struct vm_area_struct pvma; - struct page *page; /* Create a pseudo vma that just contains the policy */ pvma.vm_start = 0; pvma.vm_pgoff = idx; pvma.vm_ops = NULL; pvma.vm_policy = mpol_shared_policy_lookup(&info->policy, idx); - page = alloc_page_vma(gfp, &pvma, 0); - mpol_put(pvma.vm_policy); - return page; + + /* + * alloc_page_vma() will drop the shared policy reference + */ + return alloc_page_vma(gfp, &pvma, 0); } #else /* !CONFIG_NUMA */ #ifdef CONFIG_TMPFS -- cgit v1.2.3 From bea904d54d6faa92400f10c8ea3d3828b8e1eb93 Mon Sep 17 00:00:00 2001 From: Lee Schermerhorn Date: Mon, 28 Apr 2008 02:13:18 -0700 Subject: mempolicy: use MPOL_PREFERRED for system-wide default policy Currently, when one specifies MPOL_DEFAULT via a NUMA memory policy API [set_mempolicy(), mbind() and internal versions], the kernel simply installs a NULL struct mempolicy pointer in the appropriate context: task policy, vma policy, or shared policy. This causes any use of that policy to "fall back" to the next most specific policy scope. The only use of MPOL_DEFAULT to mean "local allocation" is in the system default policy. This requires extra checks/cases for MPOL_DEFAULT in many mempolicy.c functions. There is another, "preferred" way to specify local allocation via the APIs. That is using the MPOL_PREFERRED policy mode with an empty nodemask. Internally, the empty nodemask gets converted to a preferred_node id of '-1'. All internal usage of MPOL_PREFERRED will convert the '-1' to the id of the node local to the cpu where the allocation occurs. System default policy, except during boot, is hard-coded to "local allocation". By using the MPOL_PREFERRED mode with a negative value of preferred node for system default policy, MPOL_DEFAULT will never occur in the 'policy' member of a struct mempolicy. Thus, we can remove all checks for MPOL_DEFAULT when converting policy to a node id/zonelist in the allocation paths. In slab_node() return local node id when policy pointer is NULL. No need to set a pol value to take the switch default. Replace switch default with BUG()--i.e., shouldn't happen. With this patch MPOL_DEFAULT is only used in the APIs, including internal calls to do_set_mempolicy() and in the display of policy in /proc//numa_maps. It always means "fall back" to the the next most specific policy scope. This simplifies the description of memory policies quite a bit, with no visible change in behavior. get_mempolicy() continues to return MPOL_DEFAULT and an empty nodemask when the requested policy [task or vma/shared] is NULL. These are the values one would supply via set_mempolicy() or mbind() to achieve that condition--default behavior. This patch updates Documentation to reflect this change. Signed-off-by: Lee Schermerhorn Cc: Christoph Lameter Cc: David Rientjes Cc: Mel Gorman Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/numa_memory_policy.txt | 54 +++++++++----------------- mm/mempolicy.c | 68 ++++++++++++++++++++------------- 2 files changed, 60 insertions(+), 62 deletions(-) (limited to 'Documentation') diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index 6719d642653f..13cca5a3cf17 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt @@ -147,35 +147,18 @@ Components of Memory Policies Linux memory policy supports the following 4 behavioral modes: - Default Mode--MPOL_DEFAULT: The behavior specified by this mode is - context or scope dependent. - - As mentioned in the Policy Scope section above, during normal - system operation, the System Default Policy is hard coded to - contain the Default mode. - - In this context, default mode means "local" allocation--that is - attempt to allocate the page from the node associated with the cpu - where the fault occurs. If the "local" node has no memory, or the - node's memory can be exhausted [no free pages available], local - allocation will "fallback to"--attempt to allocate pages from-- - "nearby" nodes, in order of increasing "distance". - - Implementation detail -- subject to change: "Fallback" uses - a per node list of sibling nodes--called zonelists--built at - boot time, or when nodes or memory are added or removed from - the system [memory hotplug]. These per node zonelist are - constructed with nodes in order of increasing distance based - on information provided by the platform firmware. - - When a task/process policy or a shared policy contains the Default - mode, this also means "local allocation", as described above. - - In the context of a VMA, Default mode means "fall back to task - policy"--which may or may not specify Default mode. Thus, Default - mode can not be counted on to mean local allocation when used - on a non-shared region of the address space. However, see - MPOL_PREFERRED below. + Default Mode--MPOL_DEFAULT: This mode is only used in the memory + policy APIs. Internally, MPOL_DEFAULT is converted to the NULL + memory policy in all policy scopes. Any existing non-default policy + will simply be removed when MPOL_DEFAULT is specified. As a result, + MPOL_DEFAULT means "fall back to the next most specific policy scope." + + For example, a NULL or default task policy will fall back to the + system default policy. A NULL or default vma policy will fall + back to the task policy. + + When specified in one of the memory policy APIs, the Default mode + does not use the optional set of nodes. It is an error for the set of nodes specified for this policy to be non-empty. @@ -187,19 +170,18 @@ Components of Memory Policies MPOL_PREFERRED: This mode specifies that the allocation should be attempted from the single node specified in the policy. If that - allocation fails, the kernel will search other nodes, exactly as - it would for a local allocation that started at the preferred node - in increasing distance from the preferred node. "Local" allocation - policy can be viewed as a Preferred policy that starts at the node + allocation fails, the kernel will search other nodes, in order of + increasing distance from the preferred node based on information + provided by the platform firmware. containing the cpu where the allocation takes place. Internally, the Preferred policy uses a single node--the preferred_node member of struct mempolicy. A "distinguished value of this preferred_node, currently '-1', is interpreted as "the node containing the cpu where the allocation takes - place"--local allocation. This is the way to specify - local allocation for a specific range of addresses--i.e. for - VMA policies. + place"--local allocation. "Local" allocation policy can be + viewed as a Preferred policy that starts at the node containing + the cpu where the allocation takes place. It is possible for the user to specify that local allocation is always preferred by passing an empty nodemask with this mode. diff --git a/mm/mempolicy.c b/mm/mempolicy.c index a237295f8190..fea4a5da6e44 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -104,9 +104,13 @@ static struct kmem_cache *sn_cache; policied. */ enum zone_type policy_zone = 0; +/* + * run-time system-wide default policy => local allocation + */ struct mempolicy default_policy = { .refcnt = ATOMIC_INIT(1), /* never free it */ - .mode = MPOL_DEFAULT, + .mode = MPOL_PREFERRED, + .v = { .preferred_node = -1 }, }; static const struct mempolicy_operations { @@ -189,7 +193,7 @@ static struct mempolicy *mpol_new(unsigned short mode, unsigned short flags, if (mode == MPOL_DEFAULT) { if (nodes && !nodes_empty(*nodes)) return ERR_PTR(-EINVAL); - return NULL; + return NULL; /* simply delete any existing policy */ } VM_BUG_ON(!nodes); @@ -246,7 +250,6 @@ void __mpol_put(struct mempolicy *p) { if (!atomic_dec_and_test(&p->refcnt)) return; - p->mode = MPOL_DEFAULT; kmem_cache_free(policy_cache, p); } @@ -626,13 +629,16 @@ static long do_set_mempolicy(unsigned short mode, unsigned short flags, return 0; } -/* Fill a zone bitmap for a policy */ -static void get_zonemask(struct mempolicy *p, nodemask_t *nodes) +/* + * Return nodemask for policy for get_mempolicy() query + */ +static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes) { nodes_clear(*nodes); + if (p == &default_policy) + return; + switch (p->mode) { - case MPOL_DEFAULT: - break; case MPOL_BIND: /* Fall through */ case MPOL_INTERLEAVE: @@ -686,6 +692,11 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, } if (flags & MPOL_F_ADDR) { + /* + * Do NOT fall back to task policy if the + * vma/shared policy at addr is NULL. We + * want to return MPOL_DEFAULT in this case. + */ down_read(&mm->mmap_sem); vma = find_vma_intersection(mm, addr, addr+1); if (!vma) { @@ -700,7 +711,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, return -EINVAL; if (!pol) - pol = &default_policy; + pol = &default_policy; /* indicates default behavior */ if (flags & MPOL_F_NODE) { if (flags & MPOL_F_ADDR) { @@ -715,8 +726,11 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, err = -EINVAL; goto out; } - } else - *policy = pol->mode | pol->flags; + } else { + *policy = pol == &default_policy ? MPOL_DEFAULT : + pol->mode; + *policy |= pol->flags; + } if (vma) { up_read(¤t->mm->mmap_sem); @@ -725,7 +739,7 @@ static long do_get_mempolicy(int *policy, nodemask_t *nmask, err = 0; if (nmask) - get_zonemask(pol, nmask); + get_policy_nodemask(pol, nmask); out: mpol_cond_put(pol); @@ -1286,8 +1300,7 @@ static struct mempolicy *get_vma_policy(struct task_struct *task, addr); if (vpol) pol = vpol; - } else if (vma->vm_policy && - vma->vm_policy->mode != MPOL_DEFAULT) + } else if (vma->vm_policy) pol = vma->vm_policy; } if (!pol) @@ -1334,7 +1347,6 @@ static struct zonelist *policy_zonelist(gfp_t gfp, struct mempolicy *policy) nd = first_node(policy->v.nodes); break; case MPOL_INTERLEAVE: /* should not happen */ - case MPOL_DEFAULT: nd = numa_node_id(); break; default: @@ -1369,9 +1381,15 @@ static unsigned interleave_nodes(struct mempolicy *policy) */ unsigned slab_node(struct mempolicy *policy) { - unsigned short pol = policy ? policy->mode : MPOL_DEFAULT; + if (!policy) + return numa_node_id(); + + switch (policy->mode) { + case MPOL_PREFERRED: + if (unlikely(policy->v.preferred_node >= 0)) + return policy->v.preferred_node; + return numa_node_id(); - switch (pol) { case MPOL_INTERLEAVE: return interleave_nodes(policy); @@ -1390,13 +1408,8 @@ unsigned slab_node(struct mempolicy *policy) return zone->node; } - case MPOL_PREFERRED: - if (policy->v.preferred_node >= 0) - return policy->v.preferred_node; - /* Fall through */ - default: - return numa_node_id(); + BUG(); } } @@ -1650,8 +1663,6 @@ int __mpol_equal(struct mempolicy *a, struct mempolicy *b) if (a->mode != MPOL_DEFAULT && !mpol_match_intent(a, b)) return 0; switch (a->mode) { - case MPOL_DEFAULT: - return 1; case MPOL_BIND: /* Fall through */ case MPOL_INTERLEAVE: @@ -1828,7 +1839,7 @@ void mpol_shared_policy_init(struct shared_policy *info, unsigned short policy, if (policy != MPOL_DEFAULT) { struct mempolicy *newpol; - /* Falls back to MPOL_DEFAULT on any error */ + /* Falls back to NULL policy [MPOL_DEFAULT] on any error */ newpol = mpol_new(policy, flags, policy_nodes); if (!IS_ERR(newpol)) { /* Create pseudo-vma that contains just the policy */ @@ -1952,9 +1963,14 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) char *p = buffer; int l; nodemask_t nodes; - unsigned short mode = pol ? pol->mode : MPOL_DEFAULT; + unsigned short mode; unsigned short flags = pol ? pol->flags : 0; + if (!pol || pol == &default_policy) + mode = MPOL_DEFAULT; + else + mode = pol->mode; + switch (mode) { case MPOL_DEFAULT: nodes_clear(nodes); -- cgit v1.2.3 From fc36b8d3d819047eb4d23ca079fb4d3af20ff076 Mon Sep 17 00:00:00 2001 From: Lee Schermerhorn Date: Mon, 28 Apr 2008 02:13:21 -0700 Subject: mempolicy: use MPOL_F_LOCAL to Indicate Preferred Local Policy Now that we're using "preferred local" policy for system default, we need to make this as fast as possible. Because of the variable size of the mempolicy structure [based on size of nodemasks], the preferred_node may be in a different cacheline from the mode. This can result in accessing an extra cacheline in the normal case of system default policy. Suspect this is the cause of an observed 2-3% slowdown in page fault testing relative to kernel without this patch series. To alleviate this, use an internal mode flag, MPOL_F_LOCAL in the mempolicy flags member which is guaranteed [?] to be in the same cacheline as the mode itself. Verified that reworked mempolicy now performs slightly better on 25-rc8-mm1 for both anon and shmem segments with system default and vma [preferred local] policy. Signed-off-by: Lee Schermerhorn Cc: Christoph Lameter Cc: David Rientjes Cc: Mel Gorman Cc: Andi Kleen Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/vm/numa_memory_policy.txt | 11 ++++---- include/linux/mempolicy.h | 1 + mm/mempolicy.c | 47 +++++++++++++++------------------ 3 files changed, 28 insertions(+), 31 deletions(-) (limited to 'Documentation') diff --git a/Documentation/vm/numa_memory_policy.txt b/Documentation/vm/numa_memory_policy.txt index 13cca5a3cf17..bad16d3f6a47 100644 --- a/Documentation/vm/numa_memory_policy.txt +++ b/Documentation/vm/numa_memory_policy.txt @@ -176,12 +176,11 @@ Components of Memory Policies containing the cpu where the allocation takes place. Internally, the Preferred policy uses a single node--the - preferred_node member of struct mempolicy. A "distinguished - value of this preferred_node, currently '-1', is interpreted - as "the node containing the cpu where the allocation takes - place"--local allocation. "Local" allocation policy can be - viewed as a Preferred policy that starts at the node containing - the cpu where the allocation takes place. + preferred_node member of struct mempolicy. When the internal + mode flag MPOL_F_LOCAL is set, the preferred_node is ignored and + the policy is interpreted as local allocation. "Local" allocation + policy can be viewed as a Preferred policy that starts at the node + containing the cpu where the allocation takes place. It is possible for the user to specify that local allocation is always preferred by passing an empty nodemask with this mode. diff --git a/include/linux/mempolicy.h b/include/linux/mempolicy.h index 172b9c6acb91..b0fab9e80655 100644 --- a/include/linux/mempolicy.h +++ b/include/linux/mempolicy.h @@ -50,6 +50,7 @@ enum { * are never OR'ed into the mode in mempolicy API arguments. */ #define MPOL_F_SHARED (1 << 0) /* identify shared policies */ +#define MPOL_F_LOCAL (1 << 1) /* preferred local allocation */ #ifdef __KERNEL__ diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 7b3ae977b158..143b019e9834 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -110,7 +110,7 @@ enum zone_type policy_zone = 0; struct mempolicy default_policy = { .refcnt = ATOMIC_INIT(1), /* never free it */ .mode = MPOL_PREFERRED, - .v = { .preferred_node = -1 }, + .flags = MPOL_F_LOCAL, }; static const struct mempolicy_operations { @@ -163,7 +163,7 @@ static int mpol_new_interleave(struct mempolicy *pol, const nodemask_t *nodes) static int mpol_new_preferred(struct mempolicy *pol, const nodemask_t *nodes) { if (!nodes) - pol->v.preferred_node = -1; /* local allocation */ + pol->flags |= MPOL_F_LOCAL; /* local allocation */ else if (nodes_empty(*nodes)) return -EINVAL; /* no allowed nodes */ else @@ -290,14 +290,15 @@ static void mpol_rebind_preferred(struct mempolicy *pol, if (pol->flags & MPOL_F_STATIC_NODES) { int node = first_node(pol->w.user_nodemask); - if (node_isset(node, *nodes)) + if (node_isset(node, *nodes)) { pol->v.preferred_node = node; - else - pol->v.preferred_node = -1; + pol->flags &= ~MPOL_F_LOCAL; + } else + pol->flags |= MPOL_F_LOCAL; } else if (pol->flags & MPOL_F_RELATIVE_NODES) { mpol_relative_nodemask(&tmp, &pol->w.user_nodemask, nodes); pol->v.preferred_node = first_node(tmp); - } else if (pol->v.preferred_node != -1) { + } else if (!(pol->flags & MPOL_F_LOCAL)) { pol->v.preferred_node = node_remap(pol->v.preferred_node, pol->w.cpuset_mems_allowed, *nodes); @@ -645,7 +646,7 @@ static void get_policy_nodemask(struct mempolicy *p, nodemask_t *nodes) *nodes = p->v.nodes; break; case MPOL_PREFERRED: - if (p->v.preferred_node >= 0) + if (!(p->flags & MPOL_F_LOCAL)) node_set(p->v.preferred_node, *nodes); /* else return empty node mask for local allocation */ break; @@ -1324,13 +1325,12 @@ static nodemask_t *policy_nodemask(gfp_t gfp, struct mempolicy *policy) /* Return a zonelist indicated by gfp for node representing a mempolicy */ static struct zonelist *policy_zonelist(gfp_t gfp, struct mempolicy *policy) { - int nd; + int nd = numa_node_id(); switch (policy->mode) { case MPOL_PREFERRED: - nd = policy->v.preferred_node; - if (nd < 0) - nd = numa_node_id(); + if (!(policy->flags & MPOL_F_LOCAL)) + nd = policy->v.preferred_node; break; case MPOL_BIND: /* @@ -1339,16 +1339,13 @@ static struct zonelist *policy_zonelist(gfp_t gfp, struct mempolicy *policy) * current node is part of the mask, we use the zonelist for * the first node in the mask instead. */ - nd = numa_node_id(); if (unlikely(gfp & __GFP_THISNODE) && unlikely(!node_isset(nd, policy->v.nodes))) nd = first_node(policy->v.nodes); break; case MPOL_INTERLEAVE: /* should not happen */ - nd = numa_node_id(); break; default: - nd = 0; BUG(); } return node_zonelist(nd, gfp); @@ -1379,14 +1376,15 @@ static unsigned interleave_nodes(struct mempolicy *policy) */ unsigned slab_node(struct mempolicy *policy) { - if (!policy) + if (!policy || policy->flags & MPOL_F_LOCAL) return numa_node_id(); switch (policy->mode) { case MPOL_PREFERRED: - if (unlikely(policy->v.preferred_node >= 0)) - return policy->v.preferred_node; - return numa_node_id(); + /* + * handled MPOL_F_LOCAL above + */ + return policy->v.preferred_node; case MPOL_INTERLEAVE: return interleave_nodes(policy); @@ -1666,7 +1664,8 @@ int __mpol_equal(struct mempolicy *a, struct mempolicy *b) case MPOL_INTERLEAVE: return nodes_equal(a->v.nodes, b->v.nodes); case MPOL_PREFERRED: - return a->v.preferred_node == b->v.preferred_node; + return a->v.preferred_node == b->v.preferred_node && + a->flags == b->flags; default: BUG(); return 0; @@ -1946,7 +1945,7 @@ void numa_default_policy(void) } /* - * "local" is pseudo-policy: MPOL_PREFERRED with preferred_node == -1 + * "local" is pseudo-policy: MPOL_PREFERRED with MPOL_F_LOCAL flag * Used only for mpol_to_str() */ #define MPOL_LOCAL (MPOL_INTERLEAVE + 1) @@ -1962,7 +1961,6 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) { char *p = buffer; int l; - int nid; nodemask_t nodes; unsigned short mode; unsigned short flags = pol ? pol->flags : 0; @@ -1979,11 +1977,10 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) case MPOL_PREFERRED: nodes_clear(nodes); - nid = pol->v.preferred_node; - if (nid < 0) + if (flags & MPOL_F_LOCAL) mode = MPOL_LOCAL; /* pseudo-policy */ else - node_set(nid, nodes); + node_set(pol->v.preferred_node, nodes); break; case MPOL_BIND: @@ -2004,7 +2001,7 @@ static inline int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol) strcpy(p, policy_types[mode]); p += l; - if (flags) { + if (flags & MPOL_MODE_FLAGS) { int need_bar = 0; if (buffer + maxlen < p + 2) -- cgit v1.2.3 From 31a16294261a897ab7f59a5c26e4935a851fd410 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Mon, 28 Apr 2008 02:14:18 -0700 Subject: documentation: move spidev_fdx example to its own source file Move sample source code to its own source file so that it can be used easier and build-tested/check/maintained by anyone. (Makefile changes are in a separate patch for all of Documentation/.) Signed-off-by: Randy Dunlap Acked-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/spi/spidev | 168 +---------------------------------------- Documentation/spi/spidev_fdx.c | 158 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 160 insertions(+), 166 deletions(-) create mode 100644 Documentation/spi/spidev_fdx.c (limited to 'Documentation') diff --git a/Documentation/spi/spidev b/Documentation/spi/spidev index 5c8e1b988a08..ed2da5e5b28a 100644 --- a/Documentation/spi/spidev +++ b/Documentation/spi/spidev @@ -126,8 +126,8 @@ NOTES: FULL DUPLEX CHARACTER DEVICE API ================================ -See the sample program below for one example showing the use of the full -duplex programming interface. (Although it doesn't perform a full duplex +See the spidev_fdx.c sample program for one example showing the use of the +full duplex programming interface. (Although it doesn't perform a full duplex transfer.) The model is the same as that used in the kernel spi_sync() request; the individual transfers offer the same capabilities as are available to kernel drivers (except that it's not asynchronous). @@ -141,167 +141,3 @@ and bitrate for each transfer segment.) To make a full duplex request, provide both rx_buf and tx_buf for the same transfer. It's even OK if those are the same buffer. - - -SAMPLE PROGRAM -============== - --------------------------------- CUT HERE -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - - -static int verbose; - -static void do_read(int fd, int len) -{ - unsigned char buf[32], *bp; - int status; - - /* read at least 2 bytes, no more than 32 */ - if (len < 2) - len = 2; - else if (len > sizeof(buf)) - len = sizeof(buf); - memset(buf, 0, sizeof buf); - - status = read(fd, buf, len); - if (status < 0) { - perror("read"); - return; - } - if (status != len) { - fprintf(stderr, "short read\n"); - return; - } - - printf("read(%2d, %2d): %02x %02x,", len, status, - buf[0], buf[1]); - status -= 2; - bp = buf + 2; - while (status-- > 0) - printf(" %02x", *bp++); - printf("\n"); -} - -static void do_msg(int fd, int len) -{ - struct spi_ioc_transfer xfer[2]; - unsigned char buf[32], *bp; - int status; - - memset(xfer, 0, sizeof xfer); - memset(buf, 0, sizeof buf); - - if (len > sizeof buf) - len = sizeof buf; - - buf[0] = 0xaa; - xfer[0].tx_buf = (__u64) buf; - xfer[0].len = 1; - - xfer[1].rx_buf = (__u64) buf; - xfer[1].len = len; - - status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer); - if (status < 0) { - perror("SPI_IOC_MESSAGE"); - return; - } - - printf("response(%2d, %2d): ", len, status); - for (bp = buf; len; len--) - printf(" %02x", *bp++); - printf("\n"); -} - -static void dumpstat(const char *name, int fd) -{ - __u8 mode, lsb, bits; - __u32 speed; - - if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) { - perror("SPI rd_mode"); - return; - } - if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) { - perror("SPI rd_lsb_fist"); - return; - } - if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) { - perror("SPI bits_per_word"); - return; - } - if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) { - perror("SPI max_speed_hz"); - return; - } - - printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n", - name, mode, bits, lsb ? "(lsb first) " : "", speed); -} - -int main(int argc, char **argv) -{ - int c; - int readcount = 0; - int msglen = 0; - int fd; - const char *name; - - while ((c = getopt(argc, argv, "hm:r:v")) != EOF) { - switch (c) { - case 'm': - msglen = atoi(optarg); - if (msglen < 0) - goto usage; - continue; - case 'r': - readcount = atoi(optarg); - if (readcount < 0) - goto usage; - continue; - case 'v': - verbose++; - continue; - case 'h': - case '?': -usage: - fprintf(stderr, - "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n", - argv[0]); - return 1; - } - } - - if ((optind + 1) != argc) - goto usage; - name = argv[optind]; - - fd = open(name, O_RDWR); - if (fd < 0) { - perror("open"); - return 1; - } - - dumpstat(name, fd); - - if (msglen) - do_msg(fd, msglen); - - if (readcount) - do_read(fd, readcount); - - close(fd); - return 0; -} diff --git a/Documentation/spi/spidev_fdx.c b/Documentation/spi/spidev_fdx.c new file mode 100644 index 000000000000..fc354f760384 --- /dev/null +++ b/Documentation/spi/spidev_fdx.c @@ -0,0 +1,158 @@ +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + + +static int verbose; + +static void do_read(int fd, int len) +{ + unsigned char buf[32], *bp; + int status; + + /* read at least 2 bytes, no more than 32 */ + if (len < 2) + len = 2; + else if (len > sizeof(buf)) + len = sizeof(buf); + memset(buf, 0, sizeof buf); + + status = read(fd, buf, len); + if (status < 0) { + perror("read"); + return; + } + if (status != len) { + fprintf(stderr, "short read\n"); + return; + } + + printf("read(%2d, %2d): %02x %02x,", len, status, + buf[0], buf[1]); + status -= 2; + bp = buf + 2; + while (status-- > 0) + printf(" %02x", *bp++); + printf("\n"); +} + +static void do_msg(int fd, int len) +{ + struct spi_ioc_transfer xfer[2]; + unsigned char buf[32], *bp; + int status; + + memset(xfer, 0, sizeof xfer); + memset(buf, 0, sizeof buf); + + if (len > sizeof buf) + len = sizeof buf; + + buf[0] = 0xaa; + xfer[0].tx_buf = (__u64) buf; + xfer[0].len = 1; + + xfer[1].rx_buf = (__u64) buf; + xfer[1].len = len; + + status = ioctl(fd, SPI_IOC_MESSAGE(2), xfer); + if (status < 0) { + perror("SPI_IOC_MESSAGE"); + return; + } + + printf("response(%2d, %2d): ", len, status); + for (bp = buf; len; len--) + printf(" %02x", *bp++); + printf("\n"); +} + +static void dumpstat(const char *name, int fd) +{ + __u8 mode, lsb, bits; + __u32 speed; + + if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0) { + perror("SPI rd_mode"); + return; + } + if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0) { + perror("SPI rd_lsb_fist"); + return; + } + if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0) { + perror("SPI bits_per_word"); + return; + } + if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0) { + perror("SPI max_speed_hz"); + return; + } + + printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n", + name, mode, bits, lsb ? "(lsb first) " : "", speed); +} + +int main(int argc, char **argv) +{ + int c; + int readcount = 0; + int msglen = 0; + int fd; + const char *name; + + while ((c = getopt(argc, argv, "hm:r:v")) != EOF) { + switch (c) { + case 'm': + msglen = atoi(optarg); + if (msglen < 0) + goto usage; + continue; + case 'r': + readcount = atoi(optarg); + if (readcount < 0) + goto usage; + continue; + case 'v': + verbose++; + continue; + case 'h': + case '?': +usage: + fprintf(stderr, + "usage: %s [-h] [-m N] [-r N] /dev/spidevB.D\n", + argv[0]); + return 1; + } + } + + if ((optind + 1) != argc) + goto usage; + name = argv[optind]; + + fd = open(name, O_RDWR); + if (fd < 0) { + perror("open"); + return 1; + } + + dumpstat(name, fd); + + if (msglen) + do_msg(fd, msglen); + + if (readcount) + do_read(fd, readcount); + + close(fd); + return 0; +} -- cgit v1.2.3 From 3b0cb4caefeca6fe6b05c6c5a76e9c633b44c58f Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Mon, 28 Apr 2008 02:14:30 -0700 Subject: kprobes: update document about batch registration Add the description of batch registration interfaces to Documentation/kprobes.txt. Signed-off-by: Masami Hiramatsu Cc: Ananth N Mavinakayanahalli Cc: Jim Keniston Cc: Prasanna S Panchamukhi Cc: Shaohua Li Cc: David Miller Cc: "Frank Ch. Eigler" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/kprobes.txt | 51 +++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 4 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kprobes.txt b/Documentation/kprobes.txt index be89f393274f..6877e7187113 100644 --- a/Documentation/kprobes.txt +++ b/Documentation/kprobes.txt @@ -37,6 +37,11 @@ registration function such as register_kprobe() specifies where the probe is to be inserted and what handler is to be called when the probe is hit. +There are also register_/unregister_*probes() functions for batch +registration/unregistration of a group of *probes. These functions +can speed up unregistration process when you have to unregister +a lot of probes at once. + The next three subsections explain how the different types of probes work. They explain certain things that you'll need to know in order to make the best use of Kprobes -- e.g., the @@ -190,10 +195,11 @@ code mapping. 4. API Reference The Kprobes API includes a "register" function and an "unregister" -function for each type of probe. Here are terse, mini-man-page -specifications for these functions and the associated probe handlers -that you'll write. See the files in the samples/kprobes/ sub-directory -for examples. +function for each type of probe. The API also includes "register_*probes" +and "unregister_*probes" functions for (un)registering arrays of probes. +Here are terse, mini-man-page specifications for these functions and +the associated probe handlers that you'll write. See the files in the +samples/kprobes/ sub-directory for examples. 4.1 register_kprobe @@ -319,6 +325,43 @@ void unregister_kretprobe(struct kretprobe *rp); Removes the specified probe. The unregister function can be called at any time after the probe has been registered. +NOTE: +If the functions find an incorrect probe (ex. an unregistered probe), +they clear the addr field of the probe. + +4.5 register_*probes + +#include +int register_kprobes(struct kprobe **kps, int num); +int register_kretprobes(struct kretprobe **rps, int num); +int register_jprobes(struct jprobe **jps, int num); + +Registers each of the num probes in the specified array. If any +error occurs during registration, all probes in the array, up to +the bad probe, are safely unregistered before the register_*probes +function returns. +- kps/rps/jps: an array of pointers to *probe data structures +- num: the number of the array entries. + +NOTE: +You have to allocate(or define) an array of pointers and set all +of the array entries before using these functions. + +4.6 unregister_*probes + +#include +void unregister_kprobes(struct kprobe **kps, int num); +void unregister_kretprobes(struct kretprobe **rps, int num); +void unregister_jprobes(struct jprobe **jps, int num); + +Removes each of the num probes in the specified array at once. + +NOTE: +If the functions find some incorrect probes (ex. unregistered +probes) in the specified array, they clear the addr field of those +incorrect probes. However, other probes in the array are +unregistered correctly. + 5. Kprobes Features and Limitations Kprobes allows multiple probes at the same address. Currently, -- cgit v1.2.3 From e6de1808f8ebfeb7e49f3c5a30cb8f2032beb287 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 28 Apr 2008 02:14:46 -0700 Subject: gpio: define gpio_is_valid() Introduce a gpio_is_valid() predicate; use it in gpiolib. Signed-off-by: Guennadi Liakhovetski [ use inline function; follow the gpio_* naming convention; work without gpiolib; all programming interfaces need docs ] Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/gpio.txt | 10 ++++++++++ drivers/gpio/gpiolib.c | 14 +++++++------- include/asm-generic/gpio.h | 12 ++++++++++++ 3 files changed, 29 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/gpio.txt b/Documentation/gpio.txt index 54630095aa3c..c35ca9e40d4c 100644 --- a/Documentation/gpio.txt +++ b/Documentation/gpio.txt @@ -107,6 +107,16 @@ type of GPIO controller, and on one particular board 80-95 with an FPGA. The numbers need not be contiguous; either of those platforms could also use numbers 2000-2063 to identify GPIOs in a bank of I2C GPIO expanders. +If you want to initialize a structure with an invalid GPIO number, use +some negative number (perhaps "-EINVAL"); that will never be valid. To +test if a number could reference a GPIO, you may use this predicate: + + int gpio_is_valid(int number); + +A number that's not valid will be rejected by calls which may request +or free GPIOs (see below). Other numbers may also be rejected; for +example, a number might be valid but unused on a given board. + Whether a platform supports multiple GPIO controllers is currently a platform-specific implementation issue. diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index eb75d12e83b7..623fcd9b547a 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c @@ -99,7 +99,7 @@ int gpiochip_add(struct gpio_chip *chip) * dynamic allocation. We don't currently support that. */ - if (chip->base < 0 || (chip->base + chip->ngpio) >= ARCH_NR_GPIOS) { + if (chip->base < 0 || !gpio_is_valid(chip->base + chip->ngpio)) { status = -EINVAL; goto fail; } @@ -174,7 +174,7 @@ int gpio_request(unsigned gpio, const char *label) spin_lock_irqsave(&gpio_lock, flags); - if (gpio >= ARCH_NR_GPIOS) + if (!gpio_is_valid(gpio)) goto done; desc = &gpio_desc[gpio]; if (desc->chip == NULL) @@ -209,7 +209,7 @@ void gpio_free(unsigned gpio) unsigned long flags; struct gpio_desc *desc; - if (gpio >= ARCH_NR_GPIOS) { + if (!gpio_is_valid(gpio)) { WARN_ON(extra_checks); return; } @@ -245,7 +245,7 @@ const char *gpiochip_is_requested(struct gpio_chip *chip, unsigned offset) { unsigned gpio = chip->base + offset; - if (gpio >= ARCH_NR_GPIOS || gpio_desc[gpio].chip != chip) + if (!gpio_is_valid(gpio) || gpio_desc[gpio].chip != chip) return NULL; if (test_bit(FLAG_REQUESTED, &gpio_desc[gpio].flags) == 0) return NULL; @@ -276,7 +276,7 @@ int gpio_direction_input(unsigned gpio) spin_lock_irqsave(&gpio_lock, flags); - if (gpio >= ARCH_NR_GPIOS) + if (!gpio_is_valid(gpio)) goto fail; chip = desc->chip; if (!chip || !chip->get || !chip->direction_input) @@ -314,7 +314,7 @@ int gpio_direction_output(unsigned gpio, int value) spin_lock_irqsave(&gpio_lock, flags); - if (gpio >= ARCH_NR_GPIOS) + if (!gpio_is_valid(gpio)) goto fail; chip = desc->chip; if (!chip || !chip->set || !chip->direction_output) @@ -531,7 +531,7 @@ static int gpiolib_show(struct seq_file *s, void *unused) /* REVISIT this isn't locked against gpio_chip removal ... */ - for (gpio = 0; gpio < ARCH_NR_GPIOS; gpio++) { + for (gpio = 0; gpio_is_valid(gpio); gpio++) { if (chip == gpio_desc[gpio].chip) continue; chip = gpio_desc[gpio].chip; diff --git a/include/asm-generic/gpio.h b/include/asm-generic/gpio.h index 7e77b6ff45bb..464c5b334dc2 100644 --- a/include/asm-generic/gpio.h +++ b/include/asm-generic/gpio.h @@ -16,6 +16,12 @@ #define ARCH_NR_GPIOS 256 #endif +static inline int gpio_is_valid(int number) +{ + /* only some non-negative numbers are valid */ + return ((unsigned)number) < ARCH_NR_GPIOS; +} + struct seq_file; struct module; @@ -99,6 +105,12 @@ extern int __gpio_cansleep(unsigned gpio); #else +static inline int gpio_is_valid(int number) +{ + /* only non-negative numbers are valid */ + return number >= 0; +} + /* platforms that don't directly support access to GPIOs through I2C, SPI, * or other blocking infrastructure can use these wrappers. */ -- cgit v1.2.3 From fa20c8a6e520d9ccd68c8101155ffdbc19c977c3 Mon Sep 17 00:00:00 2001 From: Andres Salomon Date: Mon, 28 Apr 2008 02:14:57 -0700 Subject: gxfb: replace FBSIZE config option with a module parameter Use a command line option (vram) rather than hardcoding the vram size. LxFB already does this; it's useful for machines that can't query the BIOS for fb size. This patch originated from David Woodhouse, was modified by Jordan Crouse, and was then modified further by me. This also adds some gxfb documentation in Documentation/fb. Signed-off-by: Andres Salomon Cc: Jordan Crouse Cc: "Antonino A. Daplas" Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/fb/gxfb.txt | 51 ++++++++++++++++++++++++++++++++++++++++ drivers/video/geode/Kconfig | 20 ---------------- drivers/video/geode/display_gx.c | 7 ------ drivers/video/geode/gxfb_core.c | 14 ++++++----- 4 files changed, 59 insertions(+), 33 deletions(-) create mode 100644 Documentation/fb/gxfb.txt (limited to 'Documentation') diff --git a/Documentation/fb/gxfb.txt b/Documentation/fb/gxfb.txt new file mode 100644 index 000000000000..b56096142017 --- /dev/null +++ b/Documentation/fb/gxfb.txt @@ -0,0 +1,51 @@ +[This file is cloned from VesaFB/aty128fb] + +What is gxfb? +================= + +This is a graphics framebuffer driver for AMD Geode GX2 based processors. + +Advantages: + + * No need to use AMD's VSA code (or other VESA emulation layer) in the + BIOS. + * It provides a nice large console (128 cols + 48 lines with 1024x768) + without using tiny, unreadable fonts. + * You can run XF68_FBDev on top of /dev/fb0 + * Most important: boot logo :-) + +Disadvantages: + + * graphic mode is slower than text mode... + + +How to use it? +============== + +Switching modes is done using gxfb.mode_option=... boot +parameter or using `fbset' program. + +See Documentation/fb/modedb.txt for more information on modedb +resolutions. + + +X11 +=== + +XF68_FBDev should generally work fine, but it is non-accelerated. + + +Configuration +============= + +You can pass kernel command line options to gxfb with gxfb. Bit Operations -!Iinclude/asm-x86/bitops_32.h +!Iinclude/asm-x86/bitops.h -- cgit v1.2.3 From a72a431bf8aefee7552bffd2bcdfd5c3a09605d1 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 18 Apr 2008 16:18:16 +0100 Subject: dontdiff: add modules.order Add modules.order to the list of files that shoud be ignored when using diff on a built kernel tree. Signed-off-by: Ben Dooks Signed-off-by: Sam Ravnborg --- Documentation/dontdiff | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/dontdiff b/Documentation/dontdiff index 354aec047c0e..feae2168634b 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -141,6 +141,7 @@ mkprep mktables mktree modpost +modules.order modversions.h* offset.h offsets.h -- cgit v1.2.3 From beda8ae7160bd7b521d9db274a27d8964dfba8ab Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Fri, 18 Apr 2008 16:28:35 +0100 Subject: dontdiff: ignore timeconst.h Ignore the autobuilt kernel/timeconst.h when using diff on an built kernel tree. Signed-off-by: Ben Dooks Signed-off-by: Sam Ravnborg --- Documentation/dontdiff | 1 + 1 file changed, 1 insertion(+) (limited to 'Documentation') diff --git a/Documentation/dontdiff b/Documentation/dontdiff index feae2168634b..881e6dd03aea 100644 --- a/Documentation/dontdiff +++ b/Documentation/dontdiff @@ -172,6 +172,7 @@ sm_tbl* split-include tags tftpboot.img +timeconst.h times.h* tkparse trix_boot.h -- cgit v1.2.3 From dfecbec8b54038ef02835d2f8181e1f44bd080d2 Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Sat, 19 Apr 2008 14:45:11 -0600 Subject: kconifg: 'select' considered less evil While select should be used with care, it is not actually evil. Signed-off-by: Matthew Wilcox Signed-off-by: Sam Ravnborg --- Documentation/kbuild/kconfig-language.txt | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'Documentation') diff --git a/Documentation/kbuild/kconfig-language.txt b/Documentation/kbuild/kconfig-language.txt index 649cb8799890..00b950d1c193 100644 --- a/Documentation/kbuild/kconfig-language.txt +++ b/Documentation/kbuild/kconfig-language.txt @@ -104,14 +104,15 @@ applicable everywhere (see syntax). Reverse dependencies can only be used with boolean or tristate symbols. Note: - select is evil.... select will by brute force set a symbol - equal to 'y' without visiting the dependencies. So abusing - select you are able to select a symbol FOO even if FOO depends - on BAR that is not set. In general use select only for - non-visible symbols (no prompts anywhere) and for symbols with - no dependencies. That will limit the usefulness but on the - other hand avoid the illegal configurations all over. kconfig - should one day warn about such things. + select should be used with care. select will force + a symbol to a value without visiting the dependencies. + By abusing select you are able to select a symbol FOO even + if FOO depends on BAR that is not set. + In general use select only for non-visible symbols + (no prompts anywhere) and for symbols with no dependencies. + That will limit the usefulness but on the other hand avoid + the illegal configurations all over. + kconfig should one day warn about such things. - numerical ranges: "range" ["if" ] This allows to limit the range of possible input values for int -- cgit v1.2.3 From e9ae71078b2c8657c0e8de808b76b76049806906 Mon Sep 17 00:00:00 2001 From: Zhang Rui Date: Tue, 22 Apr 2008 08:50:09 +0800 Subject: thermal: update the documentation Update the documentation for the thermal driver hwmon sys I/F. Change the ACPI thermal zone type to be consistent with hwmon. Signed-off-by: Zhang Rui Acked-by: Jean Delvare Signed-off-by: Len Brown --- Documentation/thermal/sysfs-api.txt | 33 +++++++++++++++++++++++++++------ drivers/acpi/thermal.c | 2 +- 2 files changed, 28 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/thermal/sysfs-api.txt b/Documentation/thermal/sysfs-api.txt index d9f28be75403..70d68ce8640a 100644 --- a/Documentation/thermal/sysfs-api.txt +++ b/Documentation/thermal/sysfs-api.txt @@ -108,10 +108,12 @@ and throttle appropriate devices. RO read only value RW read/write value -All thermal sysfs attributes will be represented under /sys/class/thermal +Thermal sysfs attributes will be represented under /sys/class/thermal. +Hwmon sysfs I/F extension is also available under /sys/class/hwmon +if hwmon is compiled in or built as a module. Thermal zone device sys I/F, created once it's registered: -|thermal_zone[0-*]: +/sys/class/thermal/thermal_zone[0-*]: |-----type: Type of the thermal zone |-----temp: Current temperature |-----mode: Working mode of the thermal zone @@ -119,7 +121,7 @@ Thermal zone device sys I/F, created once it's registered: |-----trip_point_[0-*]_type: Trip point type Thermal cooling device sys I/F, created once it's registered: -|cooling_device[0-*]: +/sys/class/thermal/cooling_device[0-*]: |-----type : Type of the cooling device(processor/fan/...) |-----max_state: Maximum cooling state of the cooling device |-----cur_state: Current cooling state of the cooling device @@ -130,10 +132,19 @@ They represent the relationship between a thermal zone and its associated coolin They are created/removed for each thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful execution. -|thermal_zone[0-*] +/sys/class/thermal/thermal_zone[0-*] |-----cdev[0-*]: The [0-*]th cooling device in the current thermal zone |-----cdev[0-*]_trip_point: Trip point that cdev[0-*] is associated with +Besides the thermal zone device sysfs I/F and cooling device sysfs I/F, +the generic thermal driver also creates a hwmon sysfs I/F for each _type_ of +thermal zone device. E.g. the generic thermal driver registers one hwmon class device +and build the associated hwmon sysfs I/F for all the registered ACPI thermal zones. +/sys/class/hwmon/hwmon[0-*]: + |-----name: The type of the thermal zone devices. + |-----temp[1-*]_input: The current temperature of thermal zone [1-*]. + |-----temp[1-*]_critical: The critical trip point of thermal zone [1-*]. +Please read Documentation/hwmon/sysfs-interface for additional information. *************************** * Thermal zone attributes * @@ -141,7 +152,10 @@ thermal_zone_bind_cooling_device/thermal_zone_unbind_cooling_device successful e type Strings which represent the thermal zone type. This is given by thermal zone driver as part of registration. - Eg: "ACPI thermal zone" indicates it's a ACPI thermal device + Eg: "acpitz" indicates it's an ACPI thermal device. + In order to keep it consistent with hwmon sys attribute, + this should be a short, lowercase string, + not containing spaces nor dashes. RO Required @@ -218,7 +232,7 @@ the sys I/F structure will be built like this: /sys/class/thermal: |thermal_zone1: - |-----type: ACPI thermal zone + |-----type: acpitz |-----temp: 37000 |-----mode: kernel |-----trip_point_0_temp: 100000 @@ -243,3 +257,10 @@ the sys I/F structure will be built like this: |-----type: Fan |-----max_state: 2 |-----cur_state: 0 + +/sys/class/hwmon: + +|hwmon0: + |-----name: acpitz + |-----temp1_input: 37000 + |-----temp1_crit: 100000 diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c index ec707ed1a70f..5e9641c93fcd 100644 --- a/drivers/acpi/thermal.c +++ b/drivers/acpi/thermal.c @@ -1136,7 +1136,7 @@ static int acpi_thermal_register_thermal_zone(struct acpi_thermal *tz) for (i = 0; i < ACPI_THERMAL_MAX_ACTIVE && tz->trips.active[i].flags.valid; i++, trips++); - tz->thermal_zone = thermal_zone_device_register("ACPI thermal zone", + tz->thermal_zone = thermal_zone_device_register("acpitz", trips, tz, &acpi_thermal_zone_ops); if (IS_ERR(tz->thermal_zone)) return -ENODEV; -- cgit v1.2.3 From b59727965d7f286489206c292e2788d4835a8a23 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:17 -0300 Subject: ACPI: thinkpad-acpi: BIOS backlight mode helper (v2.1) Lenovo ThinkPads with generic ACPI backlight level control can be easily set to react to keyboard brightness key presses in a more predictable way than what they do when in "DOS / bootloader" mode after Linux brings up the ACPI interface. The switch to the ACPI backlight mode in the firmware is designed to be safe to use only as an one way trapdoor. One is not to force the firmware to switch back to "DOS/bootloader" mode except by rebooting. The mode switch itself is performed by calling any of the ACPI _BCL methods at least once. When in ACPI mode, the backlight firmware just issues (standard) events for the brightness up/down hot key presses along with the non-standard HKEY events which thinkpad-acpi traps, and doesn't touch the hardware. thinkpad-acpi will: 1. Place the ThinkPad firmware in ACPI backlight control mode if one is available 2. Suppress HKEY backlight change notifications by default to avoid double-reporting when ACPI video is loaded when the ThinkPad is in ACPI backlight control mode 3. Urge the user to load the ACPI video driver The user is free to use either the ACPI video driver to get the brightness key events, or to override the thinkpad-acpi default hotkey mask to get them from thinkpad-acpi as well (this will result in duplicate events if ACPI video is loaded, so let's hope distros won't screw this up). Provided userspace is sane, all should work (and *keep* working), which is more that can be said about the non-ACPI mode of the new Lenovo ThinkPad BIOSes when coupled to current userspace and X.org drivers. Full guidelines for backlight hot key reporting and use of the thinkpad-acpi backlight interface have been added to the documentation. Signed-off-by: Henrique de Moraes Holschuh Cc: Matthew Garrett Cc: Thomas Renninger Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 50 +++++++ drivers/misc/thinkpad_acpi.c | 238 ++++++++++++++++++-------------- 2 files changed, 183 insertions(+), 105 deletions(-) (limited to 'Documentation') diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 76cb428435da..a77da28a6f8e 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -571,6 +571,47 @@ netlink interface and the input layer interface, and don't bother at all with hotkey_report_mode. +Brightness hotkey notes: + +These are the current sane choices for brightness key mapping in +thinkpad-acpi: + +For IBM and Lenovo models *without* ACPI backlight control (the ones on +which thinkpad-acpi will autoload its backlight interface by default, +and on which ACPI video does not export a backlight interface): + +1. Don't enable or map the brightness hotkeys in thinkpad-acpi, as + these older firmware versions unfortunately won't respect the hotkey + mask for brightness keys anyway, and always reacts to them. This + usually work fine, unless X.org drivers are doing something to block + the BIOS. In that case, use (3) below. This is the default mode of + operation. + +2. Enable the hotkeys, but map them to something else that is NOT + KEY_BRIGHTNESS_UP/DOWN or any other keycode that would cause + userspace to try to change the backlight level, and use that as an + on-screen-display hint. + +3. IF AND ONLY IF X.org drivers find a way to block the firmware from + automatically changing the brightness, enable the hotkeys and map + them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN, and feed that to + something that calls xbacklight. thinkpad-acpi will not be able to + change brightness in that case either, so you should disable its + backlight interface. + +For Lenovo models *with* ACPI backlight control: + +1. Load up ACPI video and use that. ACPI video will report ACPI + events for brightness change keys. Do not mess with thinkpad-acpi + defaults in this case. thinkpad-acpi should not have anything to do + with backlight events in a scenario where ACPI video is loaded: + brightness hotkeys must be disabled, and the backlight interface is + to be kept disabled as well. This is the default mode of operation. + +2. Do *NOT* load up ACPI video, enable the hotkeys in thinkpad-acpi, + and map them to KEY_BRIGHTNESS_UP and KEY_BRIGHTNESS_DOWN. Process + these keys on userspace somehow (e.g. by calling xbacklight). + Bluetooth --------- @@ -1090,6 +1131,15 @@ it there will be the following attributes: dim the display. +WARNING: + + Whatever you do, do NOT ever call thinkpad-acpi backlight-level change + interface and the ACPI-based backlight level change interface + (available on newer BIOSes, and driven by the Linux ACPI video driver) + at the same time. The two will interact in bad ways, do funny things, + and maybe reduce the life of the backlight lamps by needlessly kicking + its level up and down at every change. + Volume control -- /proc/acpi/ibm/volume --------------------------------------- diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 6cb781262f94..2c85a2e10a25 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -225,6 +225,7 @@ static struct { u32 light:1; u32 light_status:1; u32 bright_16levels:1; + u32 bright_acpimode:1; u32 wan:1; u32 fan_ctrl_status_undef:1; u32 input_device_registered:1; @@ -807,6 +808,80 @@ static int parse_strtoul(const char *buf, return 0; } +static int __init tpacpi_query_bcl_levels(acpi_handle handle) +{ + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *obj; + int rc; + + if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { + obj = (union acpi_object *)buffer.pointer; + if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { + printk(TPACPI_ERR "Unknown _BCL data, " + "please report this to %s\n", TPACPI_MAIL); + rc = 0; + } else { + rc = obj->package.count; + } + } else { + return 0; + } + + kfree(buffer.pointer); + return rc; +} + +static acpi_status __init tpacpi_acpi_walk_find_bcl(acpi_handle handle, + u32 lvl, void *context, void **rv) +{ + char name[ACPI_PATH_SEGMENT_LENGTH]; + struct acpi_buffer buffer = { sizeof(name), &name }; + + if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && + !strncmp("_BCL", name, sizeof(name) - 1)) { + BUG_ON(!rv || !*rv); + **(int **)rv = tpacpi_query_bcl_levels(handle); + return AE_CTRL_TERMINATE; + } else { + return AE_OK; + } +} + +/* + * Returns 0 (no ACPI _BCL or _BCL invalid), or size of brightness map + */ +static int __init tpacpi_check_std_acpi_brightness_support(void) +{ + int status; + int bcl_levels = 0; + void *bcl_ptr = &bcl_levels; + + if (!vid_handle) { + TPACPI_ACPIHANDLE_INIT(vid); + } + if (!vid_handle) + return 0; + + /* + * Search for a _BCL method, and execute it. This is safe on all + * ThinkPads, and as a side-effect, _BCL will place a Lenovo Vista + * BIOS in ACPI backlight control mode. We do NOT have to care + * about calling the _BCL method in an enabled video device, any + * will do for our purposes. + */ + + status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, + tpacpi_acpi_walk_find_bcl, NULL, + &bcl_ptr); + + if (ACPI_SUCCESS(status) && bcl_levels > 2) { + tp_features.bright_acpimode = 1; + return (bcl_levels - 2); + } + + return 0; +} + /************************************************************************* * thinkpad-acpi driver attributes */ @@ -1887,6 +1962,9 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ + /* These either have to go through ACPI video, or + * act like in the IBM ThinkPads, so don't ever + * enable them by default */ KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ KEY_RESERVED, /* 0x10: FN+END (brightness down) */ @@ -2091,6 +2169,32 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) set_bit(SW_TABLET_MODE, tpacpi_inputdev->swbit); } + /* Do not issue duplicate brightness change events to + * userspace */ + if (!tp_features.bright_acpimode) + /* update bright_acpimode... */ + tpacpi_check_std_acpi_brightness_support(); + + if (tp_features.bright_acpimode) { + printk(TPACPI_INFO + "This ThinkPad has standard ACPI backlight " + "brightness control, supported by the ACPI " + "video driver\n"); + printk(TPACPI_NOTICE + "Disabling thinkpad-acpi brightness events " + "by default...\n"); + + /* The hotkey_reserved_mask change below is not + * necessary while the keys are at KEY_RESERVED in the + * default map, but better safe than sorry, leave it + * here as a marker of what we have to do, especially + * when we finally become able to set this at runtime + * on response to X.org requests */ + hotkey_reserved_mask |= + (1 << TP_ACPI_HOTKEYSCAN_FNHOME) + | (1 << TP_ACPI_HOTKEYSCAN_FNEND); + } + dbg_printk(TPACPI_DBG_INIT, "enabling hot key handling\n"); res = hotkey_status_set(1); @@ -4273,100 +4377,6 @@ static struct backlight_ops ibm_backlight_data = { /* --------------------------------------------------------------------- */ -static int __init tpacpi_query_bcll_levels(acpi_handle handle) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - int rc; - - if (ACPI_SUCCESS(acpi_evaluate_object(handle, NULL, NULL, &buffer))) { - obj = (union acpi_object *)buffer.pointer; - if (!obj || (obj->type != ACPI_TYPE_PACKAGE)) { - printk(TPACPI_ERR "Unknown BCLL data, " - "please report this to %s\n", TPACPI_MAIL); - rc = 0; - } else { - rc = obj->package.count; - } - } else { - return 0; - } - - kfree(buffer.pointer); - return rc; -} - -static acpi_status __init brightness_find_bcll(acpi_handle handle, u32 lvl, - void *context, void **rv) -{ - char name[ACPI_PATH_SEGMENT_LENGTH]; - struct acpi_buffer buffer = { sizeof(name), &name }; - - if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && - !strncmp("BCLL", name, sizeof(name) - 1)) { - if (tpacpi_query_bcll_levels(handle) == 16) { - *rv = handle; - return AE_CTRL_TERMINATE; - } else { - return AE_OK; - } - } else { - return AE_OK; - } -} - -static int __init brightness_check_levels(void) -{ - int status; - void *found_node = NULL; - - if (!vid_handle) { - TPACPI_ACPIHANDLE_INIT(vid); - } - if (!vid_handle) - return 0; - - /* Search for a BCLL package with 16 levels */ - status = acpi_walk_namespace(ACPI_TYPE_PACKAGE, vid_handle, 3, - brightness_find_bcll, NULL, - &found_node); - - return (ACPI_SUCCESS(status) && found_node != NULL); -} - -static acpi_status __init brightness_find_bcl(acpi_handle handle, u32 lvl, - void *context, void **rv) -{ - char name[ACPI_PATH_SEGMENT_LENGTH]; - struct acpi_buffer buffer = { sizeof(name), &name }; - - if (ACPI_SUCCESS(acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer)) && - !strncmp("_BCL", name, sizeof(name) - 1)) { - *rv = handle; - return AE_CTRL_TERMINATE; - } else { - return AE_OK; - } -} - -static int __init brightness_check_std_acpi_support(void) -{ - int status; - void *found_node = NULL; - - if (!vid_handle) { - TPACPI_ACPIHANDLE_INIT(vid); - } - if (!vid_handle) - return 0; - - /* Search for a _BCL method, but don't execute it */ - status = acpi_walk_namespace(ACPI_TYPE_METHOD, vid_handle, 3, - brightness_find_bcl, NULL, &found_node); - - return (ACPI_SUCCESS(status) && found_node != NULL); -} - static int __init brightness_init(struct ibm_init_struct *iibm) { int b; @@ -4375,13 +4385,19 @@ static int __init brightness_init(struct ibm_init_struct *iibm) mutex_init(&brightness_mutex); - if (!brightness_enable) { - dbg_printk(TPACPI_DBG_INIT, - "brightness support disabled by " - "module parameter\n"); - return 1; - } else if (brightness_enable > 1) { - if (brightness_check_std_acpi_support()) { + /* + * We always attempt to detect acpi support, so as to switch + * Lenovo Vista BIOS to ACPI brightness mode even if we are not + * going to publish a backlight interface + */ + b = tpacpi_check_std_acpi_brightness_support(); + if (b > 0) { + if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) { + printk(TPACPI_NOTICE + "Lenovo BIOS switched to ACPI backlight " + "control mode\n"); + } + if (brightness_enable > 1) { printk(TPACPI_NOTICE "standard ACPI backlight interface " "available, not loading native one...\n"); @@ -4389,6 +4405,22 @@ static int __init brightness_init(struct ibm_init_struct *iibm) } } + if (!brightness_enable) { + dbg_printk(TPACPI_DBG_INIT, + "brightness support disabled by " + "module parameter\n"); + return 1; + } + + if (b > 16) { + printk(TPACPI_ERR + "Unsupported brightness interface, " + "please contact %s\n", TPACPI_MAIL); + return 1; + } + if (b == 16) + tp_features.bright_16levels = 1; + if (!brightness_mode) { if (thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO) brightness_mode = 2; @@ -4402,10 +4434,6 @@ static int __init brightness_init(struct ibm_init_struct *iibm) if (brightness_mode > 3) return -EINVAL; - tp_features.bright_16levels = - thinkpad_id.vendor == PCI_VENDOR_ID_LENOVO && - brightness_check_levels(); - b = brightness_get(NULL); if (b < 0) return 1; -- cgit v1.2.3 From 95e57ab2cbd8b016327b23d76da8a96cbd26ac0c Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:22 -0300 Subject: ACPI: thinkpad-acpi: claim tpacpi as an official short handle (v1.1) Unfortunately, a lot of stuff in the kernel has size limitations, so "thinkpad-acpi" ends up eating up too much real estate. We were using "tpacpi" in symbols already, but this shorthand was not visible to userland. Document that the driver will use tpacpi as a short hand where necessary, and use it to name the kernel thread for NVRAM polling (now named "ktpacpi_nvramd"). Also, register a module alias with the shorthand. One can refer to the module using the shorthand name. Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 5 +++++ drivers/misc/thinkpad_acpi.c | 8 ++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) (limited to 'Documentation') diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index a77da28a6f8e..a41bc893f8d6 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -18,6 +18,11 @@ This driver used to be named ibm-acpi until kernel 2.6.21 and release moved to the drivers/misc tree and renamed to thinkpad-acpi for kernel 2.6.22, and release 0.14. +The driver is named "thinkpad-acpi". In some places, like module +names, "thinkpad_acpi" is used because of userspace issues. + +"tpacpi" is used as a shorthand where "thinkpad-acpi" would be too +long due to length limitations on some Linux kernel versions. Status ------ diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 5e25abc54008..2b73dfafac9d 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -133,8 +133,11 @@ enum { #define TPACPI_PROC_DIR "ibm" #define TPACPI_ACPI_EVENT_PREFIX "ibm" #define TPACPI_DRVR_NAME TPACPI_FILE +#define TPACPI_DRVR_SHORTNAME "tpacpi" #define TPACPI_HWMON_DRVR_NAME TPACPI_NAME "_hwmon" +#define TPACPI_NVRAM_KTHREAD_NAME "ktpacpi_nvramd" + #define TPACPI_MAX_ACPI_ARGS 3 /* Debugging */ @@ -1523,8 +1526,7 @@ static void hotkey_poll_setup(int may_warn) (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { if (!tpacpi_hotkey_task) { tpacpi_hotkey_task = kthread_run(hotkey_kthread, - NULL, - TPACPI_FILE "d"); + NULL, TPACPI_NVRAM_KTHREAD_NAME); if (IS_ERR(tpacpi_hotkey_task)) { tpacpi_hotkey_task = NULL; printk(TPACPI_ERR @@ -6316,6 +6318,8 @@ static int __init thinkpad_acpi_module_init(void) /* Please remove this in year 2009 */ MODULE_ALIAS("ibm_acpi"); +MODULE_ALIAS(TPACPI_DRVR_SHORTNAME); + /* * DMI matching for module autoloading * -- cgit v1.2.3 From e306501d1c4ff610feaba74ac35dd13e470480e6 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:24 -0300 Subject: ACPI: thinkpad-acpi: add sysfs led class support for thinklight (v3.1) Add a sysfs led class interface to the thinklight (light subdriver). Signed-off-by: Henrique de Moraes Holschuh Cc: Richard Purdie Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 25 ++++++++++++--- drivers/misc/thinkpad_acpi.c | 57 ++++++++++++++++++++++++++++++++- 2 files changed, 76 insertions(+), 6 deletions(-) (limited to 'Documentation') diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index a41bc893f8d6..af1f2bcb6f66 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -693,16 +693,31 @@ while others are still having problems. For more information: https://bugs.freedesktop.org/show_bug.cgi?id=2000 -ThinkLight control -- /proc/acpi/ibm/light ------------------------------------------- +ThinkLight control +------------------ + +procfs: /proc/acpi/ibm/light +sysfs attributes: as per led class, for the "tpacpi::thinklight" led + +procfs notes: -The current status of the ThinkLight can be found in this file. A few -models which do not make the status available will show it as -"unknown". The available commands are: +The ThinkLight status can be read and set through the procfs interface. A +few models which do not make the status available will show the ThinkLight +status as "unknown". The available commands are: echo on > /proc/acpi/ibm/light echo off > /proc/acpi/ibm/light +sysfs notes: + +The ThinkLight sysfs interface is documented by the led class +documentation, in Documentation/leds-class.txt. The ThinkLight led name +is "tpacpi::thinklight". + +Due to limitations in the sysfs led class, if the status of the thinklight +cannot be read or if it is unknown, thinkpad-acpi will report it as "off". +It is impossible to know if the status returned through sysfs is valid. + Docking / undocking -- /proc/acpi/ibm/dock ------------------------------------------ diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 5a3fb09f10d3..38a119bd931e 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -3280,13 +3280,49 @@ static int light_set_status(int status) return -ENXIO; } +static void light_set_status_worker(struct work_struct *work) +{ + struct tpacpi_led_classdev *data = + container_of(work, struct tpacpi_led_classdev, work); + + if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) + light_set_status((data->new_brightness != LED_OFF)); +} + +static void light_sysfs_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct tpacpi_led_classdev *data = + container_of(led_cdev, + struct tpacpi_led_classdev, + led_classdev); + data->new_brightness = brightness; + schedule_work(&data->work); +} + +static enum led_brightness light_sysfs_get(struct led_classdev *led_cdev) +{ + return (light_get_status() == 1)? LED_FULL : LED_OFF; +} + +static struct tpacpi_led_classdev tpacpi_led_thinklight = { + .led_classdev = { + .name = "tpacpi::thinklight", + .brightness_set = &light_sysfs_set, + .brightness_get = &light_sysfs_get, + } +}; + static int __init light_init(struct ibm_init_struct *iibm) { + int rc = 0; + vdbg_printk(TPACPI_DBG_INIT, "initializing light subdriver\n"); TPACPI_ACPIHANDLE_INIT(ledb); TPACPI_ACPIHANDLE_INIT(lght); TPACPI_ACPIHANDLE_INIT(cmos); + INIT_WORK(&tpacpi_led_thinklight.work, light_set_status_worker); /* light not supported on 570, 600e/x, 770e, 770x, G4x, R30, R31 */ tp_features.light = (cmos_handle || lght_handle) && !ledb_handle; @@ -3300,7 +3336,25 @@ static int __init light_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "light is %s\n", str_supported(tp_features.light)); - return (tp_features.light)? 0 : 1; + if (tp_features.light) { + rc = led_classdev_register(&tpacpi_pdev->dev, + &tpacpi_led_thinklight.led_classdev); + } + + if (rc < 0) { + tp_features.light = 0; + tp_features.light_status = 0; + } else { + rc = (tp_features.light)? 0 : 1; + } + return rc; +} + +static void light_exit(void) +{ + led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); + if (work_pending(&tpacpi_led_thinklight.work)) + flush_scheduled_work(); } static int light_read(char *p) @@ -3348,6 +3402,7 @@ static struct ibm_struct light_driver_data = { .name = "light", .read = light_read, .write = light_write, + .exit = light_exit, }; /************************************************************************* -- cgit v1.2.3 From af116101924914a9655dfad108548d0db58c40f9 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:25 -0300 Subject: ACPI: thinkpad-acpi: add sysfs led class support to thinkpad leds (v3.2) Add a sysfs led class interface to the led subdriver. Signed-off-by: Henrique de Moraes Holschuh Cc: Richard Purdie Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 47 +++++++++-- drivers/misc/thinkpad_acpi.c | 136 +++++++++++++++++++++++++++++++- 2 files changed, 176 insertions(+), 7 deletions(-) (limited to 'Documentation') diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index af1f2bcb6f66..73b80a7e9b03 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -876,28 +876,63 @@ The cmos command interface is prone to firmware split-brain problems, as in newer ThinkPads it is just a compatibility layer. Do not use it, it is exported just as a debug tool. -LED control -- /proc/acpi/ibm/led ---------------------------------- +LED control +----------- -Some of the LED indicators can be controlled through this feature. The -available commands are: +procfs: /proc/acpi/ibm/led +sysfs attributes: as per led class, see below for names + +Some of the LED indicators can be controlled through this feature. On +some older ThinkPad models, it is possible to query the status of the +LED indicators as well. Newer ThinkPads cannot query the real status +of the LED indicators. + +procfs notes: + +The available commands are: echo ' on' >/proc/acpi/ibm/led echo ' off' >/proc/acpi/ibm/led echo ' blink' >/proc/acpi/ibm/led The range is 0 to 7. The set of LEDs that can be -controlled varies from model to model. Here is the mapping on the X40: +controlled varies from model to model. Here is the common ThinkPad +mapping: 0 - power 1 - battery (orange) 2 - battery (green) - 3 - UltraBase + 3 - UltraBase/dock 4 - UltraBay + 5 - UltraBase battery slot + 6 - (unknown) 7 - standby All of the above can be turned on and off and can be made to blink. +sysfs notes: + +The ThinkPad LED sysfs interface is described in detail by the led class +documentation, in Documentation/leds-class.txt. + +The leds are named (in LED ID order, from 0 to 7): +"tpacpi::power", "tpacpi:orange:batt", "tpacpi:green:batt", +"tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt", +"tpacpi::unknown_led", "tpacpi::standby". + +Due to limitations in the sysfs led class, if the status of the LED +indicators cannot be read due to an error, thinkpad-acpi will report it as +a brightness of zero (same as LED off). + +If the thinkpad firmware doesn't support reading the current status, +trying to read the current LED brightness will just return whatever +brightness was last written to that attribute. + +These LEDs can blink using hardware acceleration. To request that a +ThinkPad indicator LED should blink in hardware accelerated mode, use the +"timer" trigger, and leave the delay_on and delay_off parameters set to +zero (to request hardware acceleration autodetection). + ACPI sounds -- /proc/acpi/ibm/beep ---------------------------------- diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index 38a119bd931e..2ab3633f4e56 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -277,6 +277,7 @@ struct tpacpi_led_classdev { struct led_classdev led_classdev; struct work_struct work; enum led_brightness new_brightness; + unsigned int led; }; /**************************************************************************** @@ -3814,20 +3815,38 @@ TPACPI_HANDLE(led, ec, "SLED", /* 570 */ "LED", /* all others */ ); /* R30, R31 */ +#define TPACPI_LED_NUMLEDS 8 +static struct tpacpi_led_classdev *tpacpi_leds; +static enum led_status_t tpacpi_led_state_cache[TPACPI_LED_NUMLEDS]; +static const char const *tpacpi_led_names[TPACPI_LED_NUMLEDS] = { + /* there's a limit of 19 chars + NULL before 2.6.26 */ + "tpacpi::power", + "tpacpi:orange:batt", + "tpacpi:green:batt", + "tpacpi::dock_active", + "tpacpi::bay_active", + "tpacpi::dock_batt", + "tpacpi::unknown_led", + "tpacpi::standby", +}; + static int led_get_status(unsigned int led) { int status; + enum led_status_t led_s; switch (led_supported) { case TPACPI_LED_570: if (!acpi_evalf(ec_handle, &status, "GLED", "dd", 1 << led)) return -EIO; - return (status == 0)? + led_s = (status == 0)? TPACPI_LED_OFF : ((status == 1)? TPACPI_LED_ON : TPACPI_LED_BLINK); + tpacpi_led_state_cache[led] = led_s; + return led_s; default: return -ENXIO; } @@ -3874,11 +3893,96 @@ static int led_set_status(unsigned int led, enum led_status_t ledstatus) rc = -ENXIO; } + if (!rc) + tpacpi_led_state_cache[led] = ledstatus; + return rc; } +static void led_sysfs_set_status(unsigned int led, + enum led_brightness brightness) +{ + led_set_status(led, + (brightness == LED_OFF) ? + TPACPI_LED_OFF : + (tpacpi_led_state_cache[led] == TPACPI_LED_BLINK) ? + TPACPI_LED_BLINK : TPACPI_LED_ON); +} + +static void led_set_status_worker(struct work_struct *work) +{ + struct tpacpi_led_classdev *data = + container_of(work, struct tpacpi_led_classdev, work); + + if (likely(tpacpi_lifecycle == TPACPI_LIFE_RUNNING)) + led_sysfs_set_status(data->led, data->new_brightness); +} + +static void led_sysfs_set(struct led_classdev *led_cdev, + enum led_brightness brightness) +{ + struct tpacpi_led_classdev *data = container_of(led_cdev, + struct tpacpi_led_classdev, led_classdev); + + data->new_brightness = brightness; + schedule_work(&data->work); +} + +static int led_sysfs_blink_set(struct led_classdev *led_cdev, + unsigned long *delay_on, unsigned long *delay_off) +{ + struct tpacpi_led_classdev *data = container_of(led_cdev, + struct tpacpi_led_classdev, led_classdev); + + /* Can we choose the flash rate? */ + if (*delay_on == 0 && *delay_off == 0) { + /* yes. set them to the hardware blink rate (1 Hz) */ + *delay_on = 500; /* ms */ + *delay_off = 500; /* ms */ + } else if ((*delay_on != 500) || (*delay_off != 500)) + return -EINVAL; + + data->new_brightness = TPACPI_LED_BLINK; + schedule_work(&data->work); + + return 0; +} + +static enum led_brightness led_sysfs_get(struct led_classdev *led_cdev) +{ + int rc; + + struct tpacpi_led_classdev *data = container_of(led_cdev, + struct tpacpi_led_classdev, led_classdev); + + rc = led_get_status(data->led); + + if (rc == TPACPI_LED_OFF || rc < 0) + rc = LED_OFF; /* no error handling in led class :( */ + else + rc = LED_FULL; + + return rc; +} + +static void led_exit(void) +{ + unsigned int i; + + for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { + if (tpacpi_leds[i].led_classdev.name) + led_classdev_unregister(&tpacpi_leds[i].led_classdev); + } + + kfree(tpacpi_leds); + tpacpi_leds = NULL; +} + static int __init led_init(struct ibm_init_struct *iibm) { + unsigned int i; + int rc; + vdbg_printk(TPACPI_DBG_INIT, "initializing LED subdriver\n"); TPACPI_ACPIHANDLE_INIT(led); @@ -3899,6 +4003,35 @@ static int __init led_init(struct ibm_init_struct *iibm) vdbg_printk(TPACPI_DBG_INIT, "LED commands are %s, mode %d\n", str_supported(led_supported), led_supported); + tpacpi_leds = kzalloc(sizeof(*tpacpi_leds) * TPACPI_LED_NUMLEDS, + GFP_KERNEL); + if (!tpacpi_leds) { + printk(TPACPI_ERR "Out of memory for LED data\n"); + return -ENOMEM; + } + + for (i = 0; i < TPACPI_LED_NUMLEDS; i++) { + tpacpi_leds[i].led = i; + + tpacpi_leds[i].led_classdev.brightness_set = &led_sysfs_set; + tpacpi_leds[i].led_classdev.blink_set = &led_sysfs_blink_set; + if (led_supported == TPACPI_LED_570) + tpacpi_leds[i].led_classdev.brightness_get = + &led_sysfs_get; + + tpacpi_leds[i].led_classdev.name = tpacpi_led_names[i]; + + INIT_WORK(&tpacpi_leds[i].work, led_set_status_worker); + + rc = led_classdev_register(&tpacpi_pdev->dev, + &tpacpi_leds[i].led_classdev); + if (rc < 0) { + tpacpi_leds[i].led_classdev.name = NULL; + led_exit(); + return rc; + } + } + return (led_supported != TPACPI_LED_NONE)? 0 : 1; } @@ -3969,6 +4102,7 @@ static struct ibm_struct led_driver_data = { .name = "led", .read = led_read, .write = led_write, + .exit = led_exit, }; /************************************************************************* -- cgit v1.2.3 From 65807cc284dd291b024dd6e55de88feb16b4230a Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:26 -0300 Subject: ACPI: thinkpad-acpi: use uppercase for "LED" on user documentation Change all occourences of the "led" word to full uppercase in user documentation. Signed-off-by: Henrique de Moraes Holschuh Acked-by: Randy Dunlap Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) (limited to 'Documentation') diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 73b80a7e9b03..947b72654e36 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -697,7 +697,7 @@ ThinkLight control ------------------ procfs: /proc/acpi/ibm/light -sysfs attributes: as per led class, for the "tpacpi::thinklight" led +sysfs attributes: as per LED class, for the "tpacpi::thinklight" LED procfs notes: @@ -710,11 +710,11 @@ status as "unknown". The available commands are: sysfs notes: -The ThinkLight sysfs interface is documented by the led class -documentation, in Documentation/leds-class.txt. The ThinkLight led name +The ThinkLight sysfs interface is documented by the LED class +documentation, in Documentation/leds-class.txt. The ThinkLight LED name is "tpacpi::thinklight". -Due to limitations in the sysfs led class, if the status of the thinklight +Due to limitations in the sysfs LED class, if the status of the thinklight cannot be read or if it is unknown, thinkpad-acpi will report it as "off". It is impossible to know if the status returned through sysfs is valid. @@ -880,7 +880,7 @@ LED control ----------- procfs: /proc/acpi/ibm/led -sysfs attributes: as per led class, see below for names +sysfs attributes: as per LED class, see below for names Some of the LED indicators can be controlled through this feature. On some older ThinkPad models, it is possible to query the status of the @@ -891,11 +891,11 @@ procfs notes: The available commands are: - echo ' on' >/proc/acpi/ibm/led - echo ' off' >/proc/acpi/ibm/led - echo ' blink' >/proc/acpi/ibm/led + echo ' on' >/proc/acpi/ibm/led + echo ' off' >/proc/acpi/ibm/led + echo ' blink' >/proc/acpi/ibm/led -The range is 0 to 7. The set of LEDs that can be +The range is 0 to 7. The set of LEDs that can be controlled varies from model to model. Here is the common ThinkPad mapping: @@ -912,7 +912,7 @@ All of the above can be turned on and off and can be made to blink. sysfs notes: -The ThinkPad LED sysfs interface is described in detail by the led class +The ThinkPad LED sysfs interface is described in detail by the LED class documentation, in Documentation/leds-class.txt. The leds are named (in LED ID order, from 0 to 7): @@ -920,7 +920,7 @@ The leds are named (in LED ID order, from 0 to 7): "tpacpi::dock_active", "tpacpi::bay_active", "tpacpi::dock_batt", "tpacpi::unknown_led", "tpacpi::standby". -Due to limitations in the sysfs led class, if the status of the LED +Due to limitations in the sysfs LED class, if the status of the LED indicators cannot be read due to an error, thinkpad-acpi will report it as a brightness of zero (same as LED off). -- cgit v1.2.3 From 68f12ae5d778279e13e406d3913c74c592307770 Mon Sep 17 00:00:00 2001 From: Henrique de Moraes Holschuh Date: Sat, 26 Apr 2008 01:02:30 -0300 Subject: ACPI: thinkpad-acpi: bump up version to 0.20 Full LED sysfs support, and the rest of the assorted minor fixes and enhancements are a good reason to checkpoint a new version... Signed-off-by: Henrique de Moraes Holschuh Signed-off-by: Len Brown --- Documentation/laptops/thinkpad-acpi.txt | 4 ++-- drivers/misc/thinkpad_acpi.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'Documentation') diff --git a/Documentation/laptops/thinkpad-acpi.txt b/Documentation/laptops/thinkpad-acpi.txt index 947b72654e36..01c6c3d8a7e3 100644 --- a/Documentation/laptops/thinkpad-acpi.txt +++ b/Documentation/laptops/thinkpad-acpi.txt @@ -1,7 +1,7 @@ ThinkPad ACPI Extras Driver - Version 0.19 - January 06th, 2008 + Version 0.20 + April 09th, 2008 Borislav Deianov Henrique de Moraes Holschuh diff --git a/drivers/misc/thinkpad_acpi.c b/drivers/misc/thinkpad_acpi.c index d5c08c01fd11..d29ad2e4afc2 100644 --- a/drivers/misc/thinkpad_acpi.c +++ b/drivers/misc/thinkpad_acpi.c @@ -21,7 +21,7 @@ * 02110-1301, USA. */ -#define TPACPI_VERSION "0.19" +#define TPACPI_VERSION "0.20" #define TPACPI_SYSFS_VERSION 0x020200 /* -- cgit v1.2.3